eventfd(一)
函数原型: 创建的时候可以传入一个计数器的初始值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
- 设置了EFD_SEMAPHORE标志位,则返回1,且计数器中的值也减去1。
- 没有设置EFD_SEMAPHORE标志位,则返回计数器中的值,且计数器置0。
- 如果计数器中的值为0
- 设置了EFD_NONBLOCK标志位就直接返回-1。
- 没有设置EFD_NONBLOCK标志位就会一直阻塞直到计数器中的值大于0。
write: 向计数器中写入值
- 如果写入值的和小于0xFFFFFFFFFFFFFFFE,则写入成功
- 如果写入值的和大于0xFFFFFFFFFFFFFFFE
- 设置了EFD_NONBLOCK标志位就直接返回-1。
- 如果没有设置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(一)相关推荐
- eventfd和timerfd
在学习muduo中有看到eventfd和timerfd这2个函数,它们都可以通过文件描述符操作,能够很好的与epoll结合. eventfd用来在进程或线程之间通信,接口如下: ...
- Linux 新api eventfd(转)
转自http://www.cppblog.com/peija/archive/2010/10/07/128941.html eventfd 在内核版本,2.6.22以后有效.查看内核版本可以用命令 u ...
- 线程间通信之eventfd
线程间通信之eventfd man手册中的解释: eventfd()创建了一个"eventfd对象", 通过它能够实现用户态程序间(我觉得这里主要指线程而非进程)的等待/通知机制, ...
- 最高效的进(线)程间通信机制--eventfd
我们常用的进程(线程)间通信机制有管道,信号,消息队列,信号量,共享内存,socket等等,其中主要作为进程(线程)间通知/等待的有管道pipe和socketpair.线程还有特别的condition ...
- eventfd(三)
1. 测试代码: //https://www.jianshu.com/p/d7ebac8dc9f8 #include <stdio.h> #include <unistd.h> ...
- 让事件飞——Linux eventfd 原理
让事件飞--Linux eventfd 原理 让事件飞 --Linux eventfd 原理与实践 原文作者:杨阳 eventfd/timerfd 简介 目前越来越多的应用程序采用事件驱动的方式实现功 ...
- linux新的API signalfd、timerfd、eventfd使用说明
三种新的fd加入linux内核的的版本: signalfd:2.6.22 timerfd:2.6.25 eventfd:2.6.22 三种fd的意义: signalfd:传统的处理信号的方式是注册信号 ...
- eventfd以及epoll原理分析
这两天公司代码中用到了epoll.然后在跟同事闲扯的过程中发现了Linux中有eventfd.两者虽然名字看起来差不多,但是相关性倒是不多. 为了弄明白这两个东西到底在内核上是怎么实现的,这两天将内核 ...
- eventfd man
概要 #include<sys/eventfd.h> int eventfd(unsigned int initval, intflags); 描述 eventfd()创建 ...
最新文章
- 【教程】1、加载静态内容
- golang mysql多表查询_MySQL多表查询
- 深思:如何堂堂正正的做事
- SQL Server 2008 认证之路
- jdbc驱动jar_Javagt; 连接数据库时,JDBC和Mybatis的区别
- Linux下的socket演示程序
- spring-基于注解的aop开发(快速入门)
- C++学习笔记(五)--指针、NULL、引用
- Linux 安装loadrunner 碰到的问题
- html5 数据初始化,使用HTML5中的element.dataset操作自定义data-*数据
- 一种语音识别的自动控制系统及方法与流程
- Flink的容错机制
- django数据模型中关于on_delete的使用
- [CF321E] Ciel and Gondolas
- 手机型号修改 java_Android 中的设置关于手机中的型号的更改
- WINCC报表 VBS脚本链接SQL Server数据库 日报月报 导出EXCEL PDF
- PS 2020版本放大工具无法鼠标左右拖动精细放大的解决方案
- 状态模式,懂你的另一半
- 什么时候,董明珠能成功卖给记者一部格力手机?
- windows进程被占用,文件夹被占用解除被占用的方法
热门文章
- 64位CentOS6.2安装erlang及rabbitmqServer
- SharePoint 2013 开发——其他社交功能
- poj 1862 Stripies/优先队列
- POJ 1860: Currency Exchange 【SPFA】
- 【SQL】sql版Split函数。用于拆分字符串为单列表格
- java代码编写的文本特征提取_Test1 java语言写的特征提取源代码,有搞文字识别的可以下载一看,简单易学 Develop 274万源代码下载- www.pudn.com...
- 链表排序c++代码_[链表面试算法](一) 链表的删除-相关题型总结(6题)
- gitlab使用_使用 Docker 部署 Gitlab
- 二元置信椭圆r语言_医学统计与R语言:圆形树状图(circular dendrogram)
- 餐饮水单打印软件_开发一款餐饮手机app系统软件什么价格?有哪些方面需要考虑?...