函数原型: 创建的时候可以传入一个计数器的初始值initval。 第二个参数flags在linux 2.6.26之前的版本是没有使用的,必须初始化为0,在2.6.27之后的版本flag才被使用。

#include <sys/eventfd.h>
int eventfd(unsigned int initval, int flags);

分析:

flags 可以是以下值的 OR 运算结果,用以改变 eventfd 的行为。

  • EFD_CLOEXEC (since Linux 2.6.27) 文件被设置成 O_CLOEXEC,创建子进程 (fork) 时不继承父进程的文件描述符。
  • EFD_NONBLOCK (since Linux 2.6.27) 文件被设置成 O_NONBLOCK,执行 read / write 操作时,不会阻塞。
  • EFD_SEMAPHORE (since Linux 2.6.30) 提供类似信号量语义的 read 操作,简单说就是计数值 count 递减 1。

在 Linux 2.6.26 版本之前,没有使用参数 flags,必须指定为 0。

操作方法

read: 读取计数器中的值

  • 如果计数器中的值大于0

    1. 设置了EFD_SEMAPHORE标志位,则返回1,且计数器中的值也减去1。
    2. 没有设置EFD_SEMAPHORE标志位,则返回计数器中的值,且计数器置0。
  • 如果计数器中的值为0
    1. 设置了EFD_NONBLOCK标志位就直接返回-1。
    2. 没有设置EFD_NONBLOCK标志位就会一直阻塞直到计数器中的值大于0。

write: 向计数器中写入值

  • 如果写入值的和小于0xFFFFFFFFFFFFFFFE,则写入成功
  • 如果写入值的和大于0xFFFFFFFFFFFFFFFE
    1. 设置了EFD_NONBLOCK标志位就直接返回-1。
    2. 如果没有设置EFD_NONBLOCK标志位,则会一直阻塞直到read操作执行

close: 关闭文件描述符,eventfd 对象引用计数减 1,若减为 0,则释放 eventfd 对象资源。

测试代码:

#include <sys/eventfd.h>
#include <unistd.h>
#include <stdlib.h>
#include <stdio.h>
#include <stdint.h>#define handle_error(msg) do { perror(msg); exit(EXIT_FAILURE); } while (0)int main(int argc, char* argv[])
{int efd, j;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)handle_error("eventfd");switch (fork()){case 0:for (j = 1; j < argc; j++){printf("Child writing %s to efd\n", argv[j]);u = atoi(argv[j]);s = write(efd, &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(efd, &u, sizeof(uint64_t));if (s != sizeof(uint64_t)){handle_error("read");}printf("Parent read %llu (0x%llx) from efd\n",(unsigned long long) u, (unsigned long long) u);exit(EXIT_SUCCESS);case -1:handle_error("fork");}
}

输出结果:

2. 测试代码:

#include <sys/eventfd.h>
#include <unistd.h>
#include <stdlib.h>
#include <stdio.h>
#include <stdint.h>#define handle_error(msg) do { perror(msg); exit(EXIT_FAILURE); } while (0)int main(int argc, char* argv[])
{int efd, j;uint64_t u;ssize_t s;if (argc < 2){fprintf(stderr, "Usage: %s <num>...\n", argv[0]);exit(EXIT_FAILURE);}efd = eventfd(0, EFD_NONBLOCK);if (efd == -1)handle_error("eventfd");switch (fork()){case 0:for (j = 1; j < argc; j++){printf("Child writing %s to efd\n", argv[j]);}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)){handle_error("read");}printf("Parent read %llu (0x%llx) from efd\n",(unsigned long long) u, (unsigned long long) u);exit(EXIT_SUCCESS);case -1:handle_error("fork");}
}

输出结果:

3.

#include <sys/eventfd.h>
#include <unistd.h>
#include <stdlib.h>
#include <stdio.h>
#include <stdint.h>#define handle_error(msg) do { perror(msg); exit(EXIT_FAILURE); } while (0)int main(int argc, char* argv[])
{int efd, j;uint64_t u;ssize_t s;if (argc < 2){fprintf(stderr, "Usage: %s <num>...\n", argv[0]);exit(EXIT_FAILURE);}efd = eventfd(0, EFD_SEMAPHORE);if (efd == -1)handle_error("eventfd");switch (fork()){case 0:for (j = 1; j < argc; j++){printf("Child writing %s to efd\n", argv[j]);u = atoi(argv[j]);s = write(efd, &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(efd, &u, sizeof(uint64_t));if (s != sizeof(uint64_t)){handle_error("read");}printf("Parent read %llu (0x%llx) from efd\n",(unsigned long long) u, (unsigned long long) u);exit(EXIT_SUCCESS);case -1:handle_error("fork");}
}

输出结果:

参考资料:

  • Linux进程间通信-eventf
  • 通过实例来理解 eventfd 函数机制

eventfd(一)相关推荐

  1. eventfd和timerfd

    在学习muduo中有看到eventfd和timerfd这2个函数,它们都可以通过文件描述符操作,能够很好的与epoll结合.        eventfd用来在进程或线程之间通信,接口如下:     ...

  2. Linux 新api eventfd(转)

    转自http://www.cppblog.com/peija/archive/2010/10/07/128941.html eventfd 在内核版本,2.6.22以后有效.查看内核版本可以用命令 u ...

  3. 线程间通信之eventfd

    线程间通信之eventfd man手册中的解释: eventfd()创建了一个"eventfd对象", 通过它能够实现用户态程序间(我觉得这里主要指线程而非进程)的等待/通知机制, ...

  4. 最高效的进(线)程间通信机制--eventfd

    我们常用的进程(线程)间通信机制有管道,信号,消息队列,信号量,共享内存,socket等等,其中主要作为进程(线程)间通知/等待的有管道pipe和socketpair.线程还有特别的condition ...

  5. eventfd(三)

    1. 测试代码: //https://www.jianshu.com/p/d7ebac8dc9f8 #include <stdio.h> #include <unistd.h> ...

  6. 让事件飞——Linux eventfd 原理

    让事件飞--Linux eventfd 原理 让事件飞 --Linux eventfd 原理与实践 原文作者:杨阳 eventfd/timerfd 简介 目前越来越多的应用程序采用事件驱动的方式实现功 ...

  7. linux新的API signalfd、timerfd、eventfd使用说明

    三种新的fd加入linux内核的的版本: signalfd:2.6.22 timerfd:2.6.25 eventfd:2.6.22 三种fd的意义: signalfd:传统的处理信号的方式是注册信号 ...

  8. eventfd以及epoll原理分析

    这两天公司代码中用到了epoll.然后在跟同事闲扯的过程中发现了Linux中有eventfd.两者虽然名字看起来差不多,但是相关性倒是不多. 为了弄明白这两个东西到底在内核上是怎么实现的,这两天将内核 ...

  9. eventfd man

    概要     #include<sys/eventfd.h>     int eventfd(unsigned int initval, intflags); 描述 eventfd()创建 ...

最新文章

  1. 【Android 应用开发】Google 官方 EasyPermissions 权限申请库 ( 权限申请原理对话框操作回调接口 | 永久拒绝权限后引导设用户置权限 )
  2. WEB前端:浏览器(IE+Chrome+Firefox)常见兼容问题处理【01】
  3. Linux 安装Opencv3.2
  4. 什么是顺序执行以及其特点
  5. 苹果切换输入法_日语输入法哪个好
  6. hashmap另一种初始化
  7. 浅谈服务器使用RAID5磁盘阵列的问题
  8. CentOS6.6部署VNC服务端
  9. 拓端tecdat|Python基于粒子群优化的投资组合优化研究
  10. 【SpringBoot_ANNOTATIONS】 生命周期 03 @PostConstruct @PreDestroy
  11. 计算机网络笔记整理(第七版)谢希仁
  12. 快捷连接 残差_残差网络解决了什么问题
  13. 哮喘病人小气道上皮细胞 (Asthma) Small airway epithelial cells 培养解决方案
  14. fiddler抓包 - Android 虚拟机
  15. 如何批量将多个 PPT 文档按指定页分别拆分成多个文档
  16. 多多自走棋改动_《多多自走棋》 更新,几大改动来袭,一个改动让玩家无奈!...
  17. 实验六:分析Linux内核创建一个新进程的过程
  18. 《痞子衡嵌入式半月刊》 第 51 期
  19. Unity模糊远处物体,近处清晰,景深效果
  20. CODE[VS] 1219 骑士游历

热门文章

  1. 元素分类--块级元素(特点:独占一行, 宽高边距可改)
  2. BCD码与十进制的相互转换
  3. css中em与px的介绍及换算方法
  4. Web开发常出现的错误[个人收集]
  5. COM原理及应用之可连接对象
  6. bmp调色板颜色信息重复_如何更改 Linux 终端颜色主题 | Linux 中国
  7. 小数前的0在html不显示,jsp小数显示问题 例如 我在oracle 数据库中查询出来的是 0.01 但是在jsp页面上就显示成 .01 没有前面的0...
  8. 虚拟机游戏获取服务器地址,vue获取服务器地址
  9. 修改linux绑定的域名,手工修改linux系统下DA面板绑定的域名
  10. php基础是什么,php基础学什么?