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
    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 函数机制
  •  

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.mzph.cn/news/385185.shtml

如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈email:809451989@qq.com,一经查实,立即删除!

相关文章

gettimeofday

作用&#xff1a;需要打印代码执行到某处的时间&#xff0c;或者需要计算程序执行的时间差&#xff08;精确到微妙级&#xff09;。这时会用到gettimeofday函数&#xff0c;它可以返回自1970-01-01 00:00:00到现在经历的秒数。 #include <sys/time.h> int gettimeofday(…

02-线性结构2 一元多项式的乘法与加法运算 (20 分

设计函数分别求两个一元多项式的乘积与和。 输入格式: 输入分2行&#xff0c;每行分别先给出多项式非零项的个数&#xff0c;再以指数递降方式输入一个多项式非零项系数和指数&#xff08;绝对值均为不超过1000的整数&#xff09;。数字间以空格分隔。 输出格式: 输出分2行&…

1066 图像过滤 (15 分)

图像过滤是把图像中不重要的像素都染成背景色&#xff0c;使得重要部分被凸显出来。现给定一幅黑白图像&#xff0c;要求你将灰度值位于某指定区间内的所有像素颜色都用一种指定的颜色替换。 输入格式&#xff1a; 输入在第一行给出一幅图像的分辨率&#xff0c;即两个正整数 M…

从零实现一个http服务器

如果GET请求带参数&#xff0c;那么一般是附加在请求的url后面&#xff0c;参数与参数之间使用&分割&#xff0c;例如请求http://www.hootina.org/index_2013.php?param1value1m2value2m3value3&#xff0c;我们看下这个请求组装的的http协议包格式&#xff1a; GET /ind…

1068 万绿丛中一点红 (20 分)

对于计算机而言&#xff0c;颜色不过是像素点对应的一个 24 位的数值。现给定一幅分辨率为 MN 的画&#xff0c;要求你找出万绿丛中的一点红&#xff0c;即有独一无二颜色的那个像素点&#xff0c;并且该点的颜色与其周围 8 个相邻像素的颜色差充分大。 输入格式&#xff1a; 输…

《个人项目学习指引》

1. 从零实现一个http服务器

1069 微博转发抽奖 (20 分)

小明 PAT 考了满分&#xff0c;高兴之余决定发起微博转发抽奖活动&#xff0c;从转发的网友中按顺序每隔 N 个人就发出一个红包。请你编写程序帮助他确定中奖名单。 输入格式&#xff1a; 输入第一行给出三个正整数 M&#xff08;≤ 1000&#xff09;、N 和 S&#xff0c;分别是…

【1】TCP三次握手的第三次的 ack包丢失会怎样?

面试题&#xff1a; 在 TCP 建立连接的三次握手连接阶段&#xff0c;如果客户端发送的第三个ACK包丢了&#xff0c;那么客户端和服务端分别进行什么处理呢&#xff1f; 相信了解 tcp 协议的人&#xff0c;三次握手的过程肯定很了解了。第三次的 ack 包丢失就是说在 client 端…

1070 结绳 (25 分

给定一段一段的绳子&#xff0c;你需要把它们串成一条绳。每次串连的时候&#xff0c;是把两段绳子对折&#xff0c;再如下图所示套接在一起。这样得到的绳子又被当成是另一段绳子&#xff0c;可以再次对折去跟另一段绳子串连。每次串连后&#xff0c;原来两段绳子的长度就会减…

动态规划目录

序号题目1 70. 爬楼梯

1071 小赌怡情 (15 分)

常言道“小赌怡情”。这是一个很简单的小游戏&#xff1a;首先由计算机给出第一个整数&#xff1b;然后玩家下注赌第二个整数将会比第一个数大还是小&#xff1b;玩家下注 t 个筹码后&#xff0c;计算机给出第二个数。若玩家猜对了&#xff0c;则系统奖励玩家 t 个筹码&#xf…

53. 最大子序和

给定一个整数数组 nums &#xff0c;找到一个具有最大和的连续子数组&#xff08;子数组最少包含一个元素&#xff09;&#xff0c;返回其最大和。 示例: 输入: [-2,1,-3,4,-1,2,1,-5,4], 输出: 6 解释: 连续子数组 [4,-1,2,1] 的和最大&#xff0c;为 6。 进阶: 如果你已经实现…

1072 开学寄语 (20 分)

下图是上海某校的新学期开学寄语&#xff1a;天将降大任于斯人也&#xff0c;必先删其微博&#xff0c;卸其 QQ&#xff0c;封其电脑&#xff0c;夺其手机&#xff0c;收其 ipad&#xff0c;断其 wifi&#xff0c;使其百无聊赖&#xff0c;然后&#xff0c;净面、理发、整衣&am…

九大经典算法之插入排序、希尔排序

01 插入排序(Insertion Sort) 原理&#xff1a;每次选择一个元素&#xff0c;并且将这个元素和整个数组中的所有元素进行比较&#xff0c;然后插入到合适的位置。 void insertion_sort(int arr[], int n) {int i,j;for (i 1; i < n; i) {int tmp arr[i];for (j i; j >…

九大经典算法之冒泡排序、快速排序

03 冒泡排序(Bubble Sort) 每次选择两个元素&#xff0c;按照需求进行交换&#xff08;比如需要升序排列的话&#xff0c;把较大的元素放在靠后一些的位置&#xff09;&#xff0c;循环 n 次&#xff08;n 为总元素个数&#xff09;&#xff0c;这样小的元素会不断 “冒泡” 到…

1073 多选题常见计分法 (20 分)

批改多选题是比较麻烦的事情&#xff0c;有很多不同的计分方法。有一种最常见的计分方法是&#xff1a;如果考生选择了部分正确选项&#xff0c;并且没有选择任何错误选项&#xff0c;则得到 50% 分数&#xff1b;如果考生选择了任何一个错误的选项&#xff0c;则不能得分。本题…

《二叉树》目录

序号题目标记 1 94. 二叉树的中序遍历 2 98. 验证二叉搜索树 3100. 相同的树 4101. 对称二叉树 5 102. 二叉树的层次遍历 6 103. 二叉树的锯齿形层次遍历 7104. 二叉树的最大深度 8 105. 从前序与中序遍历序列构造二叉树 9106. 从中序与后序遍历序列构造二叉树 10107. 二叉…

1075 链表元素分类 (25 分)

给定一个单链表&#xff0c;请编写程序将链表元素进行分类排列&#xff0c;使得所有负值元素都排在非负值元素的前面&#xff0c;而 [0, K] 区间内的元素都排在大于 K 的元素前面。但每一类内部元素的顺序是不能改变的。例如&#xff1a;给定链表为 18→7→-4→0→5→-6→10→1…

C++ 面试(一)

1. 编译器什么情况下&#xff0c;合成构造函数&#xff1f;[点击链接(一)] 编译器什么情况下&#xff0c;合成构造函数&#xff1f;

1074 宇宙无敌加法器 (20 分)

地球人习惯使用十进制数&#xff0c;并且默认一个数字的每一位都是十进制的。而在 PAT 星人开挂的世界里&#xff0c;每个数字的每一位都是不同进制的&#xff0c;这种神奇的数字称为“PAT数”。每个 PAT 星人都必须熟记各位数字的进制表&#xff0c;例如“……0527”就表示最低…