Skip to content
Advertisement

Writing to eventfd from kernel module

I have created an eventfd instance in a userspace program using eventfd(). Is there a way in which I can pass some reference (a pointer to its struct or pid+fd pair) to this created instance of eventfd to a kernel module so that it can update the counter value?

Here is what I want to do: I am developing a userspace program which needs to exchange data and signals with a kernel space module which I have written. For transferring data, I am already using ioctl. But I want the kernel module to be able to signal the userspace program whenever new data is ready for it to consume over ioctl.

To do this, my userspace program will create a few eventfds in various threads. These threads will wait on these eventfds using select() and whenever the kernel module updates the counts on these eventfds, they will go on to consume the data by requesting for it over ioctl.

The problem is, how do I resolve the “struct file *” pointers to these eventfds from kernelspace? What kind of information bout the eventfds can I sent to kernel modules so that it can get the pointers to the eventfds? what functions would I use in the kernel module to get those pointers?

Is there better way to signal events to userspace from kernelspace? I cannot let go of using select().

Advertisement

Answer

I finally figured out how to do this. I realized that each open file on a system could be identified by the pid of one of the processes which opened it and the fd corresponding to that file (within that process’s context). So if my kernel module knows the pid and fd, it can look up the struct * task_struct of the process and from that the struct * files and finally using the fd, it can acquire the pointer to the eventfd’s struct * file. Then, using this last pointer, it can write to the eventfd’s counter.

Here are the codes for the userspace program and the kernel module that I wrote up to demonstrate the concept (which now work):

Userspace C code (efd_us.c):

JavaScript

Kernel Module C code (efd_lkm.c):

JavaScript

To run this, carry out the following steps:

  1. Compile the userspace program (efd_us.out) and the kernel module (efd_lkm.ko)
  2. Run the userspace program (./efd_us.out) and note the pid and efd values that it print. (for eg. “pid=2803 efd=3”. The userspace program will wait endlessly on select()
  3. Open a new terminal window and insert the kernel module passing the pid and efd as params: sudo insmod efd_lkm.ko pid=2803 efd=3
  4. Switch back to the userspace program window and you will see that the userspace program has broken out of select and exited.
User contributions licensed under: CC BY-SA
10 People found this is helpful
Advertisement