API说明
•eventfd API •int eventfd(unsigned int initval, int flags); –用来创建一个用于事件通知的eventfd对象 –返回值为一个int型fd,用来引用打开的对象 –打开的对象在内核中是一个64位的无符号整型计数器,初始化为initval –计数器数据类型:typedef uint64_t eventfd_t •flags: –EFD_CLOEXEC:类似于open的flags,fork子进程时不继承 –EFD_NONBLOCK:一般会设置成非阻塞 –EFD_SEMAPHORE:信号量语义的read,每次读操作,计时器值减1 •内核实现:fs/eventfd.c
举例
#include <sys/eventfd.h> #include <unistd.h> #include <stdlib.h> #include <stdio.h> #include <stdint.h> /* Definition of uint64_t */ #define handle_error(msg) \ do { perror(msg); exit(EXIT_FAILURE); } while (0) int main (int argc, char *argv[]) { int fd_event, j; uint64_t u; ssize_t s; if (argc < 2) { fprintf (stderr, "Usage: %s <num>...\n", argv[0]); exit (EXIT_FAILURE); } fd_event = eventfd(0, EFD_SEMAPHORE); if (fd_event == -1) handle_error ("eventfd"); switch (fork()) { case 0: sleep (1); for (j = 1; j < argc; j++) { printf ("Child writing %s to fd_event\n", argv[j]); u = strtoull (argv[j], NULL, 0); /* strtoull() allows various bases */ s = write (fd_event, &u, sizeof(uint64_t)); if (s != sizeof(uint64_t)) handle_error ("write"); } printf ("Child completed write loop\n"); exit (EXIT_SUCCESS); default: // sleep (2); printf ("Parent about to read\n"); s = read (fd_event, &u, sizeof(uint64_t)); if (s != sizeof(uint64_t)) handle_error ("read"); printf ("Parent read %llu (0x%llx) from fd_event\n", (unsigned long long) u, (unsigned long long) u); s = read (fd_event, &u, sizeof(uint64_t)); if (s != sizeof(uint64_t)) handle_error ("read"); printf ("Parent read %llu (0x%llx) from fd_event\n", (unsigned long long) u, (unsigned long long) u); s = read (fd_event, &u, sizeof(uint64_t)); if (s != sizeof(uint64_t)) handle_error ("read"); printf ("Parent read %llu (0x%llx) from fd_event\n", (unsigned long long) u, (unsigned long long) u); exit (EXIT_SUCCESS); case -1: handle_error ("fork"); } } // ./a.out 1 2 3 4 5 6 7 8 9