An “eventfd object” can be used as an event wait/notify mechanism by user-space applications, and by the kernel to notify user-space applications of events. It has been added to kernel since Linux 2.6.22. The object contains an unsigned 64-bit integer (uint64_t) counter that is maintained by the kernel. This counter is initialized with the value specified in the argument initval.
1 2
#include<sys/eventfd.h> inteventfd(unsignedint initval, int flags);
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):
#include<unistd.h> #include<stdlib.h> #include<stdio.h> #include<stdint.h> //Definition of uint64_t #include<sys/eventfd.h>
int efd; //Eventfd file descriptor uint64_t eftd_ctr;
int retval; //for select() fd_set rfds; //for select()
int s;
intmain(){
//Create eventfd efd = eventfd(0,0); if (efd == -1){ printf("\nUnable to create eventfd! Exiting...\n"); exit(EXIT_FAILURE); }
printf("\nefd=%d pid=%d",efd,getpid());
//Watch efd FD_ZERO(&rfds); FD_SET(efd, &rfds);
printf("\nNow waiting on select()..."); fflush(stdout);
retval = select(efd+1, &rfds, NULL, NULL, NULL);
if (retval == -1){ printf("\nselect() error. Exiting..."); exit(EXIT_FAILURE); } elseif (retval > 0) { printf("\nselect() says data is available now. Exiting..."); printf("\nreturned from select(), now executing read()..."); s = read(efd, &eftd_ctr, sizeof(uint64_t)); if (s != sizeof(uint64_t)){ printf("\neventfd read error. Exiting..."); } else { printf("\nReturned from read(), value read = %lld",eftd_ctr); } } elseif (retval == 0) { printf("\nselect() says that no data was available"); }
Compile the userspace program (efd_us.out) and the kernel module (efd_lkm.ko)
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()
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
Switch back to the userspace program window and you will see that the userspace program has broken out of select and exited.