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

最高效的进(线)程间通信机制: eventfd 一句话总结:用于进程/线程间通信,效率比pipe高 #include int eventfd(unsigned int initval, int flags); 常用的进程(线程)间通信机制有管道、信号量、消息队列、信号、共享内存、socket等等,其中主要作为进程(线程)间通知/等待的有管道pipe和socket。从Linux 2.6.27版本开始增加了eventfd,主 阅读详情


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

今天来看一个liunx较新的系统调用,它是从LINUX 2.6.27版本开始增加的,主要用于进程或者线程间的通信(如通知/等待机制的实现)。


首先来看一下函数原型:

#include <sys/eventfd.h>

       int eventfd(unsigned int initval, int flags);

下面是它man手册中的描述,我照着翻译了一遍(我英语四级434,你们要是怀疑下文的话,可以直接去man eventfd ^^):


eventfd()创建了一个"eventfd object",能在用户态用做事件wait/notify机制,通过内核取唤醒用户态的事件。这个对象保存了一个内核维护的uint64_t类型的整型counter。这个counter初始值被参数initval指定,一般初值设置为0。


它的标记可以有以下属性:

EFD_CLOECEX,EFD_NONBLOCK,EFD_SEMAPHORE。

在linux直到版本2.6.26,这个flags参数是没用的,必须指定为0。


它返回了一个引用eventfd object的描述符。这个描述符可以支持以下操作:

read:如果计数值counter的值不为0,读取成功,获得到该值。如果counter的值为0,非阻塞模式,会直接返回失败,并把errno的值指纹EINVAL。如果为阻塞模式,一直会阻塞到counter为非0位置。

write:会增加8字节的整数在计数器counter上,如果counter的值达到0xfffffffffffffffe时,就会阻塞。直到counter的值被read。阻塞和非阻塞情况同上面read一样。

close:这个操作不用说了。


重点是支持这个:

 poll(2), select(2) (and similar)
              The returned file descriptor supports poll(2) (and analogously epoll(7)) and select(2), as follows:
              *  The file descriptor is readable (the select(2) readfds argument; the poll(2) POLLIN flag) if the  counter  has  a
                 value greater than 0.
              *  The  file descriptor is writable (the select(2) writefds argument; the poll(2) POLLOUT flag) if it is possible to
                 write a value of at least "1" without blocking.
              *  If an overflow of the counter value was detected, then select(2) indicates the  file  descriptor  as  being  both
                 readable  and  writable,  and  poll(2)  returns a POLLERR event.  As noted above, write(2) can never overflow the
                 counter.  However an overflow can occur if 2^64 eventfd "signal posts" were performed by the KAIO subsystem (the‐
                 oretically possible, but practically unlikely).  If an overflow has occurred, then read(2) will return that maxi‐
                 mum uint64_t value (i.e., 0xffffffffffffffff).
              The eventfd file descriptor also supports the other file-descriptor multiplexing APIs: pselect(2) and ppoll(2)
.


它的内核代码实现是这样子的:

int eventfd_signal(struct eventfd_ctx *ctx, int n)
{
    unsigned long flags;

    if (n < 0)
        return -EINVAL;
    spin_lock_irqsave(&ctx->wqh.lock, flags);
    if (ULLONG_MAX - ctx->count < n)
        n = (int) (ULLONG_MAX - ctx->count);
    ctx->count += n;
    if (waitqueue_active(&ctx->wqh))
        wake_up_locked_poll(&ctx->wqh, POLLIN);
    spin_unlock_irqrestore(&ctx->wqh.lock, flags);

    return n;
}

本质就是做了一次唤醒,不用read,也不用write,与eventfd_write的区别是不用阻塞。


说了这么多,我们来看一个例子,理解理解其中的含义:

#include <sys/eventfd.h>
#include <unistd.h>
#include <stdlib.h>
#include <stdio.h>
#include <stdint.h>             /* Definition of uint64_t */

#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 = strtoull(argv[j], NULL, 0); 
            /* strtoull() allows various bases */
     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");
  }
}
输出:

$ ./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

注意:这里用了sleep(2)保证子进程循环写入完毕,得到的值就是综合28。如果不用sleep(2)来保证时序,当子进程写入一个值,父进程会立马从eventfd读出该值。


eventfd 和 epoll 的结合使用 这是因为,假如没有设置EPOLL_CLOEXEC标志的fork将把描述符复制到子进程中的epoll实例,当这些进程中的某一个或者多个进程关闭了其中一个文件描述符,那么可能会导致程序的不可用,或者不在我们的预期之内。size参数向内核指定内核进程需要监控的文件描述符的个数,这有助于内核决定epoll实例的大小。进程通过调用epoll_create来创建epoll实例,后续通过epoll返回的指向epoll实例的文件描述符来进行各种操作,比如添加、删除或者修改它想要件事epoll实例的I/O的其他文件描述符。 阅读详情

相关推荐

Linux·eventfd 原理与实践

Linux eventfd 原理与实践

m0_64560763的博客 2083

一起来感受下eventfd的魅力(二、kernel通过eventfd向user空间发送消息事件通知)

接下来我们来尝试写一个测试程序,该测试程序首先在用户空间创建eventfd对象,然后再通过kernel模块程序更新eventfd的计数器以实现向用户控件程序发送事件消息通知。

从0到1,突破自己 2084

Unix Domain Socket和eventfd

需要跨主机通信本地高性能IPC轻量级事件通知→ eventfd混合场景→ UDS + eventfd + epoll组合在 Linux 开发中,是一种特殊的进程间通信(IPC)机制,与和eventfd有显著区别。1. Socket Pair 是什么?定义:通过系统调用创建的一对已连接的匿名 Unix Domain Socket。特点无需绑定文件路径:直接创建一对已连接的 socket,没有文件系统路径。双向通信:两个 socket 可以互相读写(类似全双工管道)。

我的博客 1274

linux之eventfd理解

在阅读fdbus源码的过程中涉及到了eventfd,这块不是很熟悉,特此记录一下。在linux下一切皆文件,每个文件都都对应一个fd(file descriptor文件描述符),要理解eventfd,就需要对fd的类型有一个认识,fd也是有类型的,我们都知道socket fd,也知道pipe fd,timer fd,同样也有eventfd这样一种类型。

漫步者 2201

linux网络编程--eventfd

eventfd 在内核版本,2.6.22以后有效。查看内核版本可以用命令 uname -r。 eventfd类似于管道的概念,可以实现线程间的事件通知,类似于pipe。而eventfd 是一个比 pipe 更高效的线程间事件通知机制,一方面它比 pipe 少用一个 file descriper,节省了资源;另一方面,eventfd 的缓冲区管理也简单得多,全部“buffer”一共只有8字

【码农在新加坡】的专栏 4181

Linux新的API signalfd、timerfd、eventfd使用说明

三种新的fd加入linux内核的的版本:   signalfd:2.6.22   timerfd:2.6.25   eventfd:2.6.22   三种fd的意义:   lsignalfd   传统的处理信号的方式是注册信号处理函数;由于信号是异步发生的,要解决数据的并发访问,可重入问题。signalfd可以将信号抽象为一个文件描述符,当有信号发生时可以对其read,这样可以将信号的监听放到select、poll、epoll等监听队列中。   ltimerfd   可以实现定时器的功能,将定时器抽象为文件描述符,当定时器到期时可以对其read,这样也可以放到监听队列的主循环中

Linux中eventfd的讲解

eventfd。

m0_73495584的博客 1753

手把手教你用UNet实现轨道缺陷检测(附RSDDs数据集下载与完整代码)

本文详细介绍了如何使用UNet模型实现轨道缺陷检测,包括RSDDs数据集的下载与处理、UNet架构的改进与优化、训练策略设计以及模型部署的全流程。通过实战案例,展示了如何利用深度学习技术提升工业质检效率,特别适合从事工业缺陷检测和图像处理的开发者参考。

dapp9builder的博客 749

简单、高效的通信机制eventfd

eventfd`是Linux内核为用户空间程序提供的一个轻量级事件通知机制。它主要用于代替更为复杂、重量级的通知方式,如管道(pipe)等,从而为跨线程或进程间通信提供了一个简单、高效的方式。initval:计时器初始值 flags:设置下面是`eventfd`的基本原理和工作机制:1. 创建:使用`eventfd`系统调用创建一个`eventfd`对象时,内核会返回一个文件描述符。这个文件描述符可以用来进行读写操作。2. 计数器:与每个`eventfd`相关联的是一个64位的无符号整数作为。

加油加油 423

AG32VF407直流电流采集仪设计:从1uA到10A宽范围采样与FPGA加速方案

本文详细介绍了基于AG32VF407芯片的直流电流采集仪设计方案,实现了从1uA到10A的宽范围采样。方案采用低噪声电源、精密运放调理、高速比较器自动档位切换及高精度ADC同步采样,并重点阐述了利用AG32VF407片内FPGA实现硬件加速以提升性能的架构思路,为精密电流测量提供了完整的硬件与FPGA加速解决方案。

weixin_33245447的博客 312

基于Python实现的捕鱼达人小游戏源代码+使用说明

摘要: 本文介绍了一款自制的捕鱼达人小游戏,使用Python3和Pygame模块开发。游戏包含完整的资源文件(图片、音效、字体)和源码结构(11个功能模块),实现了大炮移动射击、特殊子弹、炸弹、难度递增等核心玩法。安装需配置Python环境和Pygame模块,运行main.py即可启动游戏。游戏支持键盘控制(方向键移动、空格射击、1键放炸弹),默认时长600秒,包含开始菜单、游戏界面和结束界面。所有代码均有详细注释,项目已开源并提供下载链接。(150字)

2301_76484015的博客 669

eventfd函数

eventfd是从LINUX 2.6.27版本开始增加的,主要用于进程或者线程间的通信(如通知/等待机制的实现)。实现了线程之间事件通知的方式,也可以用于用户态和内核通信。eventfd的缓冲区大小是sizeof(uint64_t);向其write可以递增这个计数器,read操作可以读取,并进行清零;eventfd也可以放到监听队列中,当计数器不是0时,有可读事件发生,可以进行读取。函数原型:#i...

Sonic_sTorm的博客 1346

Linux V4L2驱动开发实战:手把手教你用I2C摄像头Sensor注册一个v4l2_subdev

本文详细解析了Linux V4L2驱动开发中I2C摄像头Sensor注册v4l2_subdev的全流程,包括初始化、操作集填充、异步匹配等关键环节。通过实战案例和代码示例,帮助开发者掌握V4L2子系统下的摄像头驱动开发技巧,提升嵌入式Linux系统开发能力。

weixin_30328063的博客 420

Linux eventfd简介

Linux2.6.22引入了eventfd,eventfd是专门用于事件通知的文件描述符(fd)。它创建一个eventfd对象,eventfd对象不仅可以用于进程间的通信,还能用于用户态和内核态的通信。eventfd对象在内核中包含了一个计数器,该计数器是64位的无符号整数(uint64_t),计数不为零是有可读事件发生,read之后计数会清零,write则会递增计数器。...

SWX230162的博客 1575

内网Linux服务器离线安装python包

3、将下载的依赖包和requirements.txt 拷贝到内网主机,依赖包和requirements.txt放同一级目录,进入该目录,运行指令。其实还有个更加方便的办法,联网主机装个与内网主机一样环境的虚拟机,在虚拟机中下载py包,拷贝到内网主机后就能直接安装了,省去手动下载py包的步骤。简单记录下最近遇到的一个小问题,内网主机没有内网源,处于无互联网状态,安装python包只能通过联网主机下载好后拷贝到内网主机。由于内网主机安装了多个版本的python,为了防止搞错,使用这种方式来调用pip安装。

cyc头发还挺多的博客 652

让旧 Append 字段升级为真正的 Key User Custom Field:基于 SCFD_EUI 的无损转换与 UI / API 暴露实战

摘要:SAP S/4HANA私有云和本地部署项目中,常面临将历史遗留的手工追加字段转换为可管理的Custom Field的挑战。SAP提供通过事务码SCFD_EUI将旧字段转换为ABAP Managed Field(AMF)的路径,实现字段名和数据原地保留的同时获得扩展能力。适用场景包括已沉淀多年数据的字段迁移成本高,或对数据元素有特殊约束需求。转换后字段可在Fiori UI、报表、表单等多触点统一管理。但AMF会增加复杂度,建议优先使用标准Custom Field。操作前需确保开发环境和传输配置正确,并遵

2007 年 ~ 2025 年,深耕 SAP 技术 18 年 248

eventfd

eventfd的本质是一个内核维护的64位无符号整型计数器,通过文件描述符暴露给用户空间。它不是文件,也不是内核缓冲区,而是一种事件通知机制。它符合Linux"一切皆文件"的设计哲学它提供简单的事件通知机制,无需传输实际数据它与epoll等I/O多路复用机制完美集成它的实现轻量级,只需1个文件描述符,内核开销极小相比管道,eventfd更适合用于事件通知场景,而不是数据传输场景。

2301_80355452的博客 888

OpenClaw实战系列06:持久记忆与RAG知识库构建——让AI真正“记住”你

本文介绍了OpenClaw AI助理的持久记忆与RAG知识库构建功能。OpenClaw采用"文件即真理"的独特设计,所有记忆都以Markdown文件形式存储,支持直接编辑和Git版本管理。记忆系统分为三层:长期精炼记忆(MEMORY.md)、日常日志(按日期存储)和归档记忆。文章详细说明了环境配置步骤,包括安装必要组件、创建目录结构、设置API密钥,并提供了OpenClaw主配置文件的完整参数说明。该系统实现了跨会话、跨平台的持久化记忆,使AI助理能真正理解用户需求。

PeterPan的博客 1171

Linux进程间通信 --eventfd

进程间测通信 --eventfd 最近在学习多线程网络库muduo时,新学了一种新的进程通信方法eventfd。 它是从LINUX 2.6.27版本开始增加的,主要用于进程或者线程间的通信(如通知/等待机制的实现)。 我们知道,在进行IO多路复用的时候,比如select、poll、epoll等,线程会阻塞在这些监听函数上面。有时候,我们需要在没有监听事件到来时,将线程从阻塞的监听函数中唤醒。 常用的唤醒方法是:建立一个管道,将管道的一端置于监听函数上,当我们想要唤醒线程时,像管道的另一端写入数据。 even

小明的博客 530

MAX30102心率血氧传感器原理图设计,已量产(e-Health传感器)

在最近的便携健康监测设备项目中,我们采用了集成算法的 MAX30102 心率血氧模块 —— 这类带内置 MCU 算法的传感器能直接输出心率 / 血氧数值,大幅降低了主控资源占用。但硬件电路的稳定性直接决定了 PPG 信号的采集精度,下面结合实际项目里的原理图,拆解下这个模块的设计细节。

不脱发的程序猿 1283

Probability and Statistics - 4th edition

Probability and Statistics - 4th edition

linux里eventfd的原理及应用,linux里eventfd的原理及应用

一般来说:Linux进程间通信有五大方案:管道,消息队列,信号量,共享内存,套接字。管道我不是很熟,只了解一般管道局限与父子进程之间,首先就被我排除了,因为我要做的是相互独立的进程间通信,命名管道似乎不局限于父子进程,但在内核态怎么使用不清楚。消息队列完全不了解。信号量的核心是一个内核变量的原子操作,但接口只体现在用户态,而且信号量的P V操作更多做的好像是互斥,而不是我想要的通知唤醒机制。共享...

weixin_36257759的博客 455

STM32F407中文手册

STM32f407中文手册 本参考手册面向应用开发人员,提供有关使用 STM32F405xx/07xx、STM32F415xx/17xx、 STM32F42xxx 和 STM32F43xxx 微控制器存储器与外设的完整信息。STM32F405xx/07xx、STM32F415xx/17xx、STM32F42xxx 和 STM32F43xxx 构成一个微 控制器系列,各产品具有不同的存储器大小、封装和外设。有关订购信息以及器件的机械与电气特性,请参见数据手册。有关 ARM Cortex™-M4F 内核的信息,请参见《Cortex™-M4F 技术参考手册》。

eventfd介绍

eventfd是一个 Linux 系统调用,用于创建一个事件通知文件描述符。它通常用于进程间通信(IPC),允许一个进程通知另一个进程某个事件已发生。

2202_75331338的博客 589

Outlook Express 6 (OE6) for Win7/Win8/Win10

英文版 Outlook Express6.0, 兼容Win7/Win10/WinXP,解压就可用。

visio安装包

Microsoft Office Visio 是一款专业的制图软件。利用经过更新的形状、协作工具和数据链接图表,创建专业级图表以简化复杂的信息。

上一篇: muduo网络库定时器的实现
下一篇: muduo库的EventLoop类剖析
FreeeLinux
博客等级 码龄11年 421粉丝 356原创
评论
成就一亿技术人!
拼手气红包6.0元
还能输入1000个字符
 
 条评论被折叠 查看
添加红包

请填写红包祝福语或标题

个

红包个数最小为10个

元

红包金额最低5元

当前余额3.43元 前往充值 >
需支付:10.00元
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付元
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值