事件编程之eventfd
介绍
eventfd是一个内核实现的线程间/进程间通讯的事件通知机制
man
https://man7.org/linux/man-pages/man2/eventfd.2.html
int eventfd(unsigned int initval, int flags);
支持read/write/poll/select
EFD_CLOEXEC (since Linux 2.6.27)
Set the close-on-exec (FD_CLOEXEC) flag on the new file
descriptor. See the description of the O_CLOEXEC flag in
open(2) for reasons why this may be useful.
EFD_NONBLOCK (since Linux 2.6.27)
Set the O_NONBLOCK file status flag on the open file
description (see open(2)) referred to by the new file
descriptor. Using this flag saves extra calls to fcntl(2)
to achieve the same result.
EFD_SEMAPHORE (since Linux 2.6.30)
Provide semaphore-like semantics for reads from the new
file descriptor. See below.
exam
$ ./a.out 1 2 4 7 14
Child writing 1 to efd
Child writing 2 to efd
Child writing 4 to efd
Child writing 7 to efd
Child writing 14 to efd
Child completed write loop
Parent about to read
Parent read 28 (0x1c) from efd
#include <err.h>
#include <inttypes.h>
#include <stdio.h>
#include <stdlib.h>
#include <sys/eventfd.h>
#include <sys/types.h>
#include <unistd.h>
int
main(int argc, char *argv[])
{
int efd;
uint64_t u;
ssize_t s;
if (argc < 2) {
fprintf(stderr, "Usage: %s <num>...\n", argv[0]);
exit(EXIT_FAILURE);
}
efd = eventfd(0, 0);
if (efd == -1)
err(EXIT_FAILURE, "eventfd");
switch (fork()) {
case 0:
for (size_t j = 1; j < argc; j++) {
printf("Child writing %s to efd\n", argv[j]);
u = strtoull(argv[j], NULL, 0);
/* strtoull() allows various bases */
s = write(efd, &u, sizeof(uint64_t));
if (s != sizeof(uint64_t))
err(EXIT_FAILURE, "write");
}
printf("Child completed write loop\n");
exit(EXIT_SUCCESS);
default:
sleep(2);
printf("Parent about to read\n");
s = read(efd, &u, sizeof(uint64_t));
if (s != sizeof(uint64_t))
err(EXIT_FAILURE, "read");
printf("Parent read %"PRIu64" (%#"PRIx64") from efd\n", u, u);
exit(EXIT_SUCCESS);
case -1:
err(EXIT_FAILURE, "fork");
}
}
使用
创建eventfd并获取一个fd描述符
线程A:对fd写入值
线程B:对fd读取值
读写的过程是read/write堵塞操作,会有调度。
原理
系统调用 eventfd2
通过select/poll等io多路并发检测,通过read/write这种堵塞调度来实现事件的等待和执行。
内核源码:fs/eventfd.c
创建

操作

比较简单,就是基于等待队列的实现,而且也只能存val,不能存别的东西。
本质上是系统提供的一种简单通讯机制。
应用场景
高性能编程
不同线程间的同步等待可以用eventfd来简洁实现
本文来自博客园,作者:蓝天上的云℡,采用 BY-NC-SA 许可协议,转载请注明:转载自作者蓝天上的云℡ 原文链接 https://www.cnblogs.com/yucloud/p/19984464/linux_kernel_eventfd

浙公网安备 33010602011771号