Calling eventfd from Python
Eventfd is a new IPC mechanism used for signaling events between processes or between kernel and user space. It has been introduced in Linux since 2.6.22 kernel version, and in glibc since 2.8 version. This is a fairly new system function, and Python does not yet have any function that wraps this system call.
There are two ways one could call eventfd().
- Create C extension, which makes wrapper function around eventfd(), compile it and then use it from Python. Such extension module can already be found on github.
- Use ctypes module to load shared library file, which contains eventfd() function and then make a call to it. On Linux, library that contains wrappers around system functions is called GNU C Library (glibc), and it can be found through the symbolic link libc.so.6.
from ctypes import *
libc = cdll.LoadLibrary("libc.so.6")
def eventfd(init_val, flags):
return libc.eventfd(init_val, flags)
The first line imports the necessary class, then we load a glibc shared library. Now we can use this instance to call functions from it. This is what we do in the next two lines when we define a wrapper function and call eventfd() from glibc. This function is easy to call, because it takes only integer arguments and returns an integer, so there is no need to use any data types defined in ctypes, which are used to represent basic C types.
With this function created, it is possible to create new eventfd and read or write to it with Linux read and write functions.
import struct, os, sys
fd = eventfd(0, 0)
bytes_written = os.write(fd, c_ulonglong(197348329))
if bytes_written != 8:
print("Error writing to eventfd")
sys.exit(1)
num = os.read(fd, 8)
print(struct.unpack(@Q, num)[0])
num = os.read(fd, 8) # this call will block
First new eventfd is created, and its file descriptor is stored. Then we use Linux read and write functions, which operate directly through file descriptors. Eventfd accepts 8 bytes of data that are interpreted as unsigned 64 bit integer, and this is why c_ulonglong from ctypes is needed. Next line just checks if all of the 8 bytes were written. Then we read from the same file descriptor, and read the same number that was written to it. What was read is just an array of bytes that needs to be interpreted as unsigned 64 bit integer, and this is why the unpack from struct module is used with format @Q, which means interpret these bytes as unsigned 64 bit integers in the systems native endianness. Finally, we try to read again. This call blocks because there was no writing to this eventfd since the last read.
download file now