Linux新增API:eventfd
进程间等待通知机制
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
eventfd操作API
- read/eventfd_read
- 读操作将64位的计数器置0
- 如果有EFD_SEMAPHORE标记,计数器值减1
- 如果计数器值为零,继续读的话,可能会阻塞或非阻塞
- write/eventfd_write
int main(int argc, char *argv[])
{
int fd_event, j;
uint64_t u;
ssize_t s;
if (argc < 2)
{
fprintf(stderr, "Usge: %s <num>...\n", argv[0]);
exit(EXIT_FAILURE);
}
fd_event = eventfd(0, 0);
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%llu) from fd_event\n",
(unsigned long long)u, (unsigned long long)u);
exit(EXIT_SUCCESS);
case -1:
handle_error("fork");
}
return 0;
}