linux eventfd事件通知 比信号量更好用

news2024/11/20 12:26:00

  

  • 专栏内容:linux下并发编程
  • 个人主页:我的主页
  • 座右铭:天行健,君子以自强不息;地势坤,君子以厚德载物.

目录

前言

概述

原理简介

使用场景

接口说明

头文件

参数说明

代码演示

默认参数

信号量模式

结尾


前言

本专栏主要分享linux下并发编程相关知识,包括多进程,多线程,进程/线程间通信,并发同步控制,以及高并发下性能提升,请大家多多留言。


概述

eventfd 就是一个用于事件通知的fd。当然linux中,一切都可以做为文件来看待,所以就有fd。这样有一个好处管理统一,比如可以加入到epoll事件等待中。很多人可能没怎么用,但是用过的人都说:香 !

原理简介

eventfd 提供了一个进程/线程间通信的方式。

这个方式是载体是一个句柄,也就是fd,类型是eventfd,可以在/proc下查看fd时看到;

通过它可以传递事件信息,事件就是write次数累计,这个累计值用一个8字节整型值来记录,每次write时这个整型值自动会累计,它是由内核来维护,read时就会拿到累计值,并清零fd中的值。

当然这个eventfd,可以传入poll来监听,监听可读可写事件。

可写事件, eventfd的write是一直可以的,它可以不断累加,所以一直会是可写状态,所以可以不用理会可写事件。

可读事件,当eventfd的累计值为零时,为不可读状态,当大于零时,才可读。这样就提供了一种通知机制。

使用场景

适用于等待-通知的架构模式,类似于信号量的场景。

比如生产者准备好后,通知消费者;等待的消费者获取到通知后,进行消费;消费完后,消费者又开始等待。

那么,信号量也可以实现,与eventfd有什么区别呢?

两者都是内核变量,eventfd的优势在于,它可以作为文件fd来读写,同时还可以使用poll/select实现异步等待,也就是说eventfd在等待时,你还可以干别的事,如果有可读时,你再去读;而信号量则不行,只能是等待或者不等待。

接口说明

头文件

 #include <sys/eventfd.h>

创建eventfd类型的句柄

int eventfd(unsigned int initval, int flags);

参数说明

initval

计数的初值

flags

EFD_CLOEXEC:

在调用exec创建进程时会自动关闭fd。

EFD_NONBLOCK:

创建非阻塞模式的fd,也就是在计数为0时,不会等待,直接返回-1;不指定时,默认为阻塞模式。

EFD_SEMAPHORE:

创建类似信号量的模式,如果计数大于0时,每次读到的是1,同时计数自动减1,到0时阻塞。

不指定时,每次读全部累计值,计数被重置为0。

代码演示

默认参数

先看一个默认参数,默认是阻塞模式,每次都会取累计值,并重置eventfd中的累计值为零;如果累计值为0,则会阻塞。

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

int main(int argc, char *argv[])
{
        int efd;
        uint64_t u = 0;
        ssize_t s;

    efd = eventfd(0, 0);
    if (efd == -1)
                return -1;

        u = 0x01;
        printf("write eventfd %llu \n", u);
    s = write(efd, &u, sizeof(uint64_t));

        u = 0x02;
        printf("write eventfd %llu \n", u);
        s = write(efd, &u, sizeof(uint64_t));

        u = 0x03;
        printf("write eventfd %llu \n", u);
        s = write(efd, &u, sizeof(uint64_t));

        s = read(efd, &u, sizeof(uint64_t));
    if (s != sizeof(uint64_t))
        {
                printf("read failure.\n");
        }

        printf("read %llu from efd\n", u);

        close(efd);

        return 0;
}

信号量模式

再来看一下使用信号量模式的效果,虽然写入了几次,但是每次read只读出1,累计值也是每次都会减1;

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

int main(int argc, char *argv[])
{
        int efd;
        uint64_t u = 0;
        ssize_t s;

    efd = eventfd(0, EFD_SEMAPHORE);
    if (efd == -1)
                return -1;

        u = 0x01;
        printf("write eventfd %llu \n", u);
    s = write(efd, &u, sizeof(uint64_t));

        u = 0x02;
        printf("write eventfd %llu \n", u);
        s = write(efd, &u, sizeof(uint64_t));


        s = read(efd, &u, sizeof(uint64_t));
        if (s != sizeof(uint64_t))
        {
                printf("read failure.\n");
        }

        printf("read %llu from efd\n", u);

        s = read(efd, &u, sizeof(uint64_t));
        if (s != sizeof(uint64_t))
        {
                printf("read failure.\n");
        }

        printf("read %llu from efd\n", u);

        s = read(efd, &u, sizeof(uint64_t));
        if (s != sizeof(uint64_t))
        {
                printf("read failure.\n");
        }

        printf("read %llu from efd\n", u);

        close(efd);

        return 0;
}


结尾

作者邮箱:study@senllang.onaliyun.com
如有错误或者疏漏欢迎指出,互相学习。另外有什么想要了解的内容,也可以给我发邮件,互相谈讨,定知无不言。

注:未经同意,不得转载!

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

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

相关文章

1740_使用Python+ImageMagick实现图像的批量压缩

全部学习汇总&#xff1a; GreyZhang/python_basic: My learning notes about python. (github.com) 前些年使用Linux的时候为了能够方便地往网络上上传照片&#xff0c;使用shell ImageMagick的组合进行照片的批量压缩一直觉得比较方便。不过&#xff0c;那时候即使这么简单的…

JMeter从入门到精通--开始你的第一个JMeter脚本

JMeter是一款在国外非常流行和受欢迎的开源性能测试工具&#xff0c;像LoadRunner 一样&#xff0c;它也提供了一个利用本地Proxy Server&#xff08;代理服务器&#xff09;来录制生成测试脚本的功能&#xff0c;但是这个功能并不好用。所以在本文中介绍一个更为常用的方法——…

软考A计划-2023系统架构师-知识点集锦(4/4)

点击跳转专栏>Unity3D特效百例点击跳转专栏>案例项目实战源码点击跳转专栏>游戏脚本-辅助自动化点击跳转专栏>Android控件全解手册点击跳转专栏>Scratch编程案例点击跳转>软考全系列 &#x1f449;关于作者 专注于Android/Unity和各种游戏开发技巧&#xff…

redis的远程登录配置

目录 服务端&#xff1a; 客户端&#xff1a; 服务端&#xff1a; 步骤一&#xff1a;关闭防火墙 systemctl stop firewalld iptables -F setenforce 0 步骤二&#xff1a;配置/etc/redis.conf配置文件 vim /etc/redis.conf bind 127.0.0.1 改为 bind 0.0.0.0 &#xff08;…

【图书推荐 | 13】前端系列

【赠书活动第十三期 】 图书推荐 本期书籍&#xff1a;前端系列 图书列表&#xff1a; Vue.js核心技术解析Nuxt.js实战Nuxt.js Web开发实战HTML5CSS 从入门到精通Flutter2 开发实例精解Electron项目开发实战 Vue.js核心技术解析 Nuxt.js实战 Nuxt.js Web开发实战 HTML5CSS 从入…

机器鱼的制作分享

1. 运动功能说明 本文示例将实现R330样机机器鱼胸鳍能够灵活的上下摆动的功能。 2. 结构说明 本样机采用舵机模块来进行仿生机器鱼结构的设计。 胸鳍 整机 3. 电子硬件 在这个示例中&#xff0c;我们采用了以下硬件&#xff0c;请大家参考&#xff1a; 主控板 Basra主控板&…

一文搞懂ChatGPT 和 AIGC 到底是什么?【最强科普】

目录&#xff1a; 1.AIGC是什么&#xff1f; 2.ChatGPT是什么&#xff1f; 3.ChatGPT发展的几个阶段&#xff1f; 4.ChatGPT能做什么&#xff1f; 5.ChatGPT的应用场景&#xff1f; 一、AIGC是什么&#xff1f; GC&#xff08;Generated Content&#xff09;&#xff1a…

Java实训日记第六天——2023.6.12

文章目录 一、MyBatis-Plus二、将MyBatis-Plus框架整合到SpringBoot1.导依赖2.在启动类上开扫描3.在application.yml中配关于数据库的连接4.在idea中安装MyBatisX插件5.在idea中连上MySQL6.测试查询所有 3.完善增删改查功能4.逻辑删除5.自动填充 一、MyBatis-Plus 1.为什么有了…

【手撕MyBatis源码】Configuration配置体系

文章目录 Configuration概述Configuration的核心作用与配置来源配置元素元素承载配置文件解析XML文件解析流程注解配置解析 Configuration概述 Configuration 是整个MyBatis的配置体系集中管理中心&#xff0c;前文所说的Executor、StatementHandler、Cache、MappedStatement……

react---react router 5 基本使用

目录 1.路由介绍 2.路由使用 3.路由组件和一般组件 4.Switch 单一匹配 5.解决二级路由样式丢失的问题 6.路由精准匹配和模糊匹配 1.路由介绍 路由是根据不同的 URL 地址展示不同的内容或页面&#xff0c;在 SPA 应用中&#xff0c;大部分页面结果不改变&#xff0c;只改变…

PostgreSQL 对特定类索引的优化,节省磁盘空间百倍 --BRIN 索引应用在生产案例...

开头还是介绍一下群&#xff0c;如果感兴趣polardb ,mongodb ,mysql ,postgresql ,redis 等有问题&#xff0c;有需求都可以加群群内有各大数据库行业大咖&#xff0c;CTO&#xff0c;可以解决你的问题。加群请联系 liuaustin3 &#xff0c;在新加的朋友会分到2群&#xff08;共…

为生信写的Python简明教程 | 视频5

开源生信 Python教程 生信专用简明 Python 文字和视频教程 源码在&#xff1a;https://github.com/Tong-Chen/Bioinfo_course_python 目录 背景介绍 编程开篇为什么学习Python如何安装Python如何运行Python命令和脚本使用什么编辑器写Python脚本Python程序事例Python基本语法 数…

Pytorch教程:Autograd基础

PyTorch的Autograd特征可以让PyTorch灵活快速的构建机器学习项目。autograd可以实现快速和容易的多重偏微分&#xff08;梯度&#xff09;计算。偏微分计算时反向传播神经网络学习的核心。 autograd的可以在运行时动态追踪计算&#xff0c;这意味着如果模型有决策分支、或者有…

linux 系统服务管理

目录 一、chkconfig 1、列出服务列表 chkconfig --list 2、关闭开启服务 chkconfig 服务名 on/off 3、添加新服务 chkconfig --add 服务文件名 4、删除已有服务 chkconfig --del 服务名 5、系统级别定义&#xff1a; 一、chkconfig chkconfig——centos…

Python学习46:分配学号(python123)

类型&#xff1a;列表元组‪‬‪‬‪‬‪‬‪‬‮‬‪‬‫‬‪‬‪‬‪‬‪‬‪‬‮‬‪‬‭‬‪‬‪‬‪‬‪‬‪‬‮‬‫‬‮‬‪‬‪‬‪‬‪‬‪‬‮‬‭‬‫‬‪‬‪‬‪‬‪‬‪‬‮‬‫‬‪‬‪‬‪‬‪‬‪‬‪‬‮‬‭‬‫‬‪‬‪‬‪‬‪‬‪‬‮‬‫‬‪‬ 描述‪‬…

【Java项目】多种方式解决SpringBoot中遇到的控制台中文乱码问题

文章目录 配置JVM参数配置maven参数配置Runner配置Encoding通过配置文件 配置JVM参数 -Dfile.encodingUTF-8配置maven参数 重点就是 <configuration><fork>true</fork><jvmArguments>-Dfile.encodingUTF-8</jvmArguments></configuration>…

Linux常用命令——git命令

在线Linux命令查询工具 git 是目前世界上最先进的分布式版本控制系统 补充说明 git命令很多人都知道&#xff0c;Linus在1991年创建了开源的Linux&#xff0c;从此&#xff0c;Linux系统不断发展&#xff0c;已经成为最大的服务器系统软件了。 Linus虽然创建了Linux&#x…

线程池最佳实践

文章目录 yml参数配置定义参数实体bean配置线程池实战线程池高级理论线程池工作流程概述线程池拒绝策略线程池参数设置原则1&#xff09;如何为线程池设置合适的线程参数&#xff1f;2) 如何获取当前服务器的cpu核数&#xff1f;3) 无界队列问题 yml参数配置 # 定时任务线程池…

Spring高手之路1——深入理解与实现IOC依赖查找与依赖注入

本文从xml开始讲解&#xff0c;注解后面给出 文章目录 1. 一个最基本的 IOC 依赖查找实例2. IOC 的两种实现方式2.1 依赖查找&#xff08;Dependency Lookup&#xff09;2.2 依赖注入&#xff08;Dependency Injection&#xff09; 3. 在三层架构中的 service 层与 dao 层体会依…

Kafka与消息队列的比较

消息队列&#xff08;Message Queues&#xff09;是一种允许分布式系统和应用异步通信的服务。异步通信意味着消息发送者在等待接收者接收消息之前不需要等待&#xff0c;这可以提高性能和可扩展性&#xff0c;使应用能够并行处理消息。消息队列通过将消息存储在队列中来工作。…