I make simple LKM (Linux kernel module) to interact my MPI application (multi process per one compute node) at user level with kernel level information. I need to extract some data from kernel to the user level application at runtime. My MPI application uses few processes run on the same compute node simultaneously.
My LKM provides two files in /proc
. The file /proc/mylkm_input
uses to provide some virtual addresses to the LKM. The file /proc/mylkm_output
uses to read information from the LKM by my MPI application.
The application is multi processes. At least two processes can provide data into LKM and expect respond from LKM (via /proc/mylkm_output
) with data unique for particular process.
Also, the file /proc/mylkm_output
can be read by different process at the same time. To read information I do lseek(fileId, 0, SEEK_SET)
and then read(fileId, buffer, size)
Are any solutions to make LKM multi-process safe?
Thank you
Sergey
Update
I implemented following code as proposed below. I hope this is help me to make the LKM process-safe.
#define CPES_MAX_PPN 128 typedef struct CPESProcessInfoT { pid_t localPID; unsigned long virtualAddress; } CPESProcessInfo; static CPESProcessInfo addrVA[CPES_MAX_PPN];//using this due many processes use this LKM on the machine (PPN>1) static int maxItemInAddrVA = 0;//number of cells allocated by the process PID CPESProcessInfo *findAddress(void) { int i = 0; struct task_struct *callerTask = current; for(i = 0; i < CPES_MAX_PPN; ++i) { CPESProcessInfo *walkAddr = addrVA + i; if(walkAddr) { if(walkAddr->localPID == callerTask->pid) { return walkAddr; } if(0 == walkAddr->localPID) { walkAddr->localPID = callerTask->pid; ++maxItemInAddrVA; return walkAddr; } } else { printk(KERN_WARNING "CPES LKM error in findAddress PPN %d maxUsed %d", CPES_MAX_PPN, maxItemInAddrVA); } } return 0; }
Advertisement
Answer
Kernel module may distinguish processes, which access the file, using variable current
:
struct task_struct* accessor = NULL; ssize_t my_write(...) { accessor = current; ... } ssize_t my_read(...) { if(accessor != current) { // This is not a process which performed .write before return -EBUSY; } ... }
Of course, storing to and loading from accessor
variable should be protected somehow from concurrent accesses (e.g., with mutexes).