坚持思考,就会很酷
在上一期 [深入理解 Linux Epoll 池] 中随便对 eventfd 提了一嘴,这是一个很妙的 fd 。下面娓娓道来。
Linux 一切皆文件,但这个文件 fd 也是有类型的,绝大部分人都知道“文件 fd”,知道 socket fd,甚至知道 pipe fd,可能都不知道 fd 还有这么一种叫做 eventfd
的类型。
不妨拆开来看,event fd ,也就是事件 fd 类型。顾名思义,就是专门用于事件通知的文件描述符( fd )。很多人可能没怎么用,但是用过的人都说:香 !
哪个版本引入的?
Linux 2.6.22
代码位于:fs/eventfd.c
“事件传递”就是通信嘛。eventfd 不仅可以用于进程间的通信,还能用于用户态和内核态的通信。
思考一个小问题:我们知道“文件”里是保存东西的,eventfd 既然对应了一个“文件”,那么这个“文件”的内容是什么呢?
划重点:eventfd 是一个计数相关的fd。计数不为零是有可读事件发生,read
之后计数会清零,write
则会递增计数器。
这个怎么理解?
在之前自制文件系统系列中提到过:文件系统的“文件”是抽象的概念,你看到的一切知识文件系统想让你看到的东西。比如 hellofs 中我们没写过任何数据,也会返回 “hello world” 的内容。这个仅仅 hook 到 read/write 调用,然后根据逻辑返回数据而已。
eventfd 也是如此,eventfd 实现了 read/write 的调用,在调用里面实现了一套计数器的逻辑。write 仅仅是加计数,read 是读计数,并且清零。
长什么样子呢?笔者找了个进程来观摩下。
root@ubuntu:~# ll /proc/14168/fd
lrwx------ 1 root root 64 Jul 10 22:12 3 -> anon_inode:[eventfd]
在 Linux 的 /proc
下每个进程都会有个目录,目录名为进程 ID 号,在这个目录能看到使用的资源信息,其中有个 fd 目录,就是进程打开的所有文件。看出猫腻了不?有个叫做 [eventfd]
的 fd 句柄。
#include <sys/eventfd.h>
int eventfd(unsigned int initval, int flags);
举个栗子:
efd = eventfd(0, 0);
if (efd == -1)
handle_error("eventfd");
这样就创建出了一个 eventfd 类型的 fd 啦。会在你的 /proc/${pid}/fd/
目录中有一个 eventfd 类型的句柄。
我怎么知道这个知识点的?
因为在 Linux 内核代码中,我看到了呀。eventfd 就实现了这几个调用。
static const struct file_operations eventfd_fops = {
#ifdef CONFIG_PROC_FS
.show_fdinfo = eventfd_show_fdinfo,
#endif
.release = eventfd_release,
.poll = eventfd_poll,
.read = eventfd_read,
.write = eventfd_write,
.llseek = noop_llseek,
};
很明显就能看到以上实现的几个调用就是 eventfd 全部的内容所在。
简单看下 eventfd 的读写究竟做了什么?
eventfd 对应的文件内容是一个 8 字节的数字,这个数字是 read/write 操作维护的计数。
首先,write 的时候,累加计数,read 的时候读取计数,并且清零。
uint64_t u;
ssize_t n;
// 写 eventfd,内部 buffer 必须是 8 字节大小;
n = write(efd, &u, sizeof(uint64_t));
// 读 eventfd
n = read(efd, &u, sizeof(uint64_t));
读写也就是 read/write,读写这个 fd 很容易理解,但是请注意了,只能 8 个字节。这个读写的内容其实是计数。
举个栗子:如下,我们连续写 3 次
// 写 3 次
write(efd, &u /* u = 1 */ , 8)
write(efd, &u /* u = 2 */ , 8)
write(efd, &u /* u = 3 */ , 8)
你猜猜读的时候,是多少?
read(ebd, &x, 8)
读到的值是 6(因为 1+2+3),理解了吧。
小结:
eventfd_write
和 eventfd_read
函数中;在 深入理解 Linux Epoll 池 提到过,不是所有的 fd 类型都可用 epoll 池来监听事件的,只有实现了 file_operation->poll
的调用的“文件” fd 才能被 epoll 管理。eventfd 刚好就实现了这个接口。
eventfd 是专门用来传递事件的 fd ,而 epoll 池则是专门用来管理事件的池子,它们两结合就妙了。
我们知道 epoll 监听的是可读可写事件。那么你想过 eventfd 的可读可写事件是啥吗?
“可读可写事件”这是个有趣的问题,我们可以去发散下,对比思考下 socket fd,文件 fd:
回到最初问题:eventfd 呢?它的可读可写事件是什么?
我们之前说过,eventfd 实现的是计数的功能。所以 eventfd 计数不为 0 ,那么 fd 是可读的。
由于 eventfd 一直可写(可以一直累计计数),所以一直有可写事件。
所以,这里有个什么隐藏知识点呢?
eventfd 如果用 epoll 监听事件,那么都是监听读事件,因为监听写事件无意义。
关闭 fd
关闭这个很容易理解,就是不需要这个 fd 了,主动调用一把 Close ,当没有人使用的时候,内核会释放这个 fd 的资源。
fd 的阻塞属性
我们知道读写 fd 的时候,可能会遇到阻塞,对于 socket fd 来说,没有数据的时候来读,则会阻塞。写 buffer 满了的时候来写,则会阻塞。
那么对于 eventfd 呢?它的阻塞有可能是怎么样的?
read eventfd 的时候,如果计数器的值为 0,就会阻塞(这种就等同于没“文件”内容)。
这种可以设置 fd 的属性为非阻塞类型,这样读的时候,如果计数器为 0 ,返回 EAGAIN 即可,这样就不会阻塞整个系统。
单独的 eventfd 看似平平无奇,但其实有非常重要的应用。下面列举几个小例子:
我们之前说过,类似于 ext4 这种文件系统的文件 fd ,其实是不能用 epoll 来管理的,网络 fd 才可以。因为磁盘文件一直可读可写。
难道文件就自绝于此吗?用不了事件机制吗?只能同步 IO 吗?
非也。Linux 内核提供了一个叫做 libaio 的机制,能够同时提交多个 io 请求给内核(这种批量递交能提高优化的概率,大量IO堆积到设备的队列中时, 内核可以发挥 IO 调度算法的优势,比如合并 IO 等)。
aio 请求完成之后,走异步的事件通知。这个事件通知的原理就是把一个 eventfd 和这个 aio 的上下文绑定起来。aio 完成,就会往 eventfd 里面写计数,从而触发可读事件。
QEMU 可以将 VM 特定地址关联一个 eventfd,对进行监听,当Guest 进行 IO 操作 exit 到 kvm 后,kvm 可以判断本次exit 是否发生在这段特定地址中,如果是则会通过使用 eventfd 进行事件通知,进行 IO 操作,这种方式对比能节省一些时间。
最简单的例子,一个消费者和多个生产者,这种就可以借助 eventfd 优雅的完成事件通知。
生产者:
多个线程,会把请求投递到一个 list 中,然后唤醒生产者。
producer:
// 投递请求到链表
list_add( global_list, request )
// 唤醒消费者处理
write(eventfd, &cnt /* 1 */ , 8)
消费者:
是一个线程,后台 loop 处理。使用 epoll 监听 eventfd 的可读事件,这样能做到一旦有请求入队,消费者就立马唤醒处理。
consumer
// 添加 eventfd 到监听池
epoll_ctl(ep, EPOLL_CTL_ADD, eventfd, &ee);
loop:
// 等待唤醒
epoll_wait(ep, ... );
// 读取新添加到列表里的元素个数,并且进行处理;
n = read(eventfd, ... )
// 遍历链表处理
for each global_list:
// do something
哈哈,奇伢想把 Linux 的句柄类型写个遍,你觉得呢?你最想看了解的是哪种类型的句柄?
本文由哈喽比特于3年以前收录,如有侵权请联系我们。
文章来源:https://mp.weixin.qq.com/s/7pp3_XdJoffrw9dxoCmnSw
京东创始人刘强东和其妻子章泽天最近成为了互联网舆论关注的焦点。有关他们“移民美国”和在美国购买豪宅的传言在互联网上广泛传播。然而,京东官方通过微博发言人发布的消息澄清了这些传言,称这些言论纯属虚假信息和蓄意捏造。
日前,据博主“@超能数码君老周”爆料,国内三大运营商中国移动、中国电信和中国联通预计将集体采购百万台规模的华为Mate60系列手机。
据报道,荷兰半导体设备公司ASML正看到美国对华遏制政策的负面影响。阿斯麦(ASML)CEO彼得·温宁克在一档电视节目中分享了他对中国大陆问题以及该公司面临的出口管制和保护主义的看法。彼得曾在多个场合表达了他对出口管制以及中荷经济关系的担忧。
今年早些时候,抖音悄然上线了一款名为“青桃”的 App,Slogan 为“看见你的热爱”,根据应用介绍可知,“青桃”是一个属于年轻人的兴趣知识视频平台,由抖音官方出品的中长视频关联版本,整体风格有些类似B站。
日前,威马汽车首席数据官梅松林转发了一份“世界各国地区拥车率排行榜”,同时,他发文表示:中国汽车普及率低于非洲国家尼日利亚,每百户家庭仅17户有车。意大利世界排名第一,每十户中九户有车。
近日,一项新的研究发现,维生素 C 和 E 等抗氧化剂会激活一种机制,刺激癌症肿瘤中新血管的生长,帮助它们生长和扩散。
据媒体援引消息人士报道,苹果公司正在测试使用3D打印技术来生产其智能手表的钢质底盘。消息传出后,3D系统一度大涨超10%,不过截至周三收盘,该股涨幅回落至2%以内。
9月2日,坐拥千万粉丝的网红主播“秀才”账号被封禁,在社交媒体平台上引发热议。平台相关负责人表示,“秀才”账号违反平台相关规定,已封禁。据知情人士透露,秀才近期被举报存在违法行为,这可能是他被封禁的部分原因。据悉,“秀才”年龄39岁,是安徽省亳州市蒙城县人,抖音网红,粉丝数量超1200万。他曾被称为“中老年...
9月3日消息,亚马逊的一些股东,包括持有该公司股票的一家养老基金,日前对亚马逊、其创始人贝索斯和其董事会提起诉讼,指控他们在为 Project Kuiper 卫星星座项目购买发射服务时“违反了信义义务”。
据消息,为推广自家应用,苹果现推出了一个名为“Apps by Apple”的网站,展示了苹果为旗下产品(如 iPhone、iPad、Apple Watch、Mac 和 Apple TV)开发的各种应用程序。
特斯拉本周在美国大幅下调Model S和X售价,引发了该公司一些最坚定支持者的不满。知名特斯拉多头、未来基金(Future Fund)管理合伙人加里·布莱克发帖称,降价是一种“短期麻醉剂”,会让潜在客户等待进一步降价。
据外媒9月2日报道,荷兰半导体设备制造商阿斯麦称,尽管荷兰政府颁布的半导体设备出口管制新规9月正式生效,但该公司已获得在2023年底以前向中国运送受限制芯片制造机器的许可。
近日,根据美国证券交易委员会的文件显示,苹果卫星服务提供商 Globalstar 近期向马斯克旗下的 SpaceX 支付 6400 万美元(约 4.65 亿元人民币)。用于在 2023-2025 年期间,发射卫星,进一步扩展苹果 iPhone 系列的 SOS 卫星服务。
据报道,马斯克旗下社交平台𝕏(推特)日前调整了隐私政策,允许 𝕏 使用用户发布的信息来训练其人工智能(AI)模型。新的隐私政策将于 9 月 29 日生效。新政策规定,𝕏可能会使用所收集到的平台信息和公开可用的信息,来帮助训练 𝕏 的机器学习或人工智能模型。
9月2日,荣耀CEO赵明在采访中谈及华为手机回归时表示,替老同事们高兴,觉得手机行业,由于华为的回归,让竞争充满了更多的可能性和更多的魅力,对行业来说也是件好事。
《自然》30日发表的一篇论文报道了一个名为Swift的人工智能(AI)系统,该系统驾驶无人机的能力可在真实世界中一对一冠军赛里战胜人类对手。
近日,非营利组织纽约真菌学会(NYMS)发出警告,表示亚马逊为代表的电商平台上,充斥着各种AI生成的蘑菇觅食科普书籍,其中存在诸多错误。
社交媒体平台𝕏(原推特)新隐私政策提到:“在您同意的情况下,我们可能出于安全、安保和身份识别目的收集和使用您的生物识别信息。”
2023年德国柏林消费电子展上,各大企业都带来了最新的理念和产品,而高端化、本土化的中国产品正在不断吸引欧洲等国际市场的目光。
罗永浩日前在直播中吐槽苹果即将推出的 iPhone 新品,具体内容为:“以我对我‘子公司’的了解,我认为 iPhone 15 跟 iPhone 14 不会有什么区别的,除了序(列)号变了,这个‘不要脸’的东西,这个‘臭厨子’。