Skip to content
Advertisement

How to make LKM multi-process safe?

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).

User contributions licensed under: CC BY-SA
3 People found this is helpful
Advertisement