0
  • 聊天消息
  • 系统消息
  • 评论与回复
登录后你可以
  • 下载海量资料
  • 学习在线课程
  • 观看技术视频
  • 写文章/发帖/加入社区
会员中心
创作中心

完善资料让更多小伙伴认识你,还能领取20积分哦,立即完善>

3天内不再提示

只需要3分钟就能让你快速了解信号驱动式IO 快来看看吧

GReq_mcu168 来源:嵌入式Hacker 作者:吴伟东Jack 2021-03-18 11:50 次阅读
加入交流群
微信小助手二维码

扫码添加小助手

加入工程师交流群

一、Linux 的 5 种 IO 模型

阻塞式 I/O:

系统调用可能因为无法立即完成而被操作系统挂起,直到等待的事件发生为止。

非阻塞式 I/O (O_NONBLOCK):

系统调用则总是立即返回,而不管事件是否已经发生。

I/O 复用 (select、poll、epoll):

通过 I/O 复用函数向内核注册一组事件,内核通过 I/O 复用函数把其中就绪的事件通知给应用程序。

信号驱动式 I/O (SIGIO):

为一个目标文件描述符指定宿主进程,当文件描述符上有事件发生时,SIGIO 的信号处理函数将被触发,然后便可对目标文件描述符执行 I/O 操作。

异步 I/O (POSIX 的 aio_ 系列函数):

异步 I/O 的读写操作总是立即返回,而不论 I/O 是否是阻塞的,真正的读写操作由内核接管。

思考一下,什么时候应该选择何种 I/O 模型?为何要这么选择?

下面重点关注信号驱动式 I/O 这一模型,其他模型可查阅文末参考书籍。

二、如何使用信号驱动式 I/O?

一般通过如下 6 个步骤来使用信号驱动式 I/O 模型。

1> 为通知信号安装处理函数。

通过 sigaction() 来完成:

intsigaction(intsignum,conststructsigaction*act,structsigaction*oldact);

默认情况下,这个通知信号为 SIGIO。

2> 为文件描述符的设置属主。

通过 fcntl() 的 F_SETOWN 操作来完成:

fcntl(fd,F_SETOWN,pid)

属主是当文件描述符上可执行 I/O 时,会接收到通知信号的进程或进程组。

pid 为正整数时,代表了进程 ID 号。

pid 为负整数时,它的绝对值就代表了进程组 ID 号。

3> 使能非阻塞 I/O。

通过 fcntl() 的 F_SETFL 操作来完成:

flags=fcntl(fd,F_GETFL); fcntl(fd,F_SETFL,flags|O_NONBLOCK);

4> 使能信号驱动 I/O。

通过 fcntl() 的 F_SETFL 操作来完成:

flags=fcntl(fd,F_GETFL); fcntl(fd,F_SETFL,flags|O_ASYNC);

5> 进程等待 "IO 就绪" 信号的到来。

当 I/O 操作就绪时,内核会给进程发送一个信号,然后调用在第 1 步中安装好的信号处理函数。

6> 进程尽可能多地执行 I/O 操作。

循环执行 I/O 系统调用直到失败为止,此时错误码为 EAGAIN 或 EWOULDBLOCK。

原因:

信号驱动 I/O 提供的是边缘触发通知,即只有当 I/O 事件发生时我们才会收到通知,

且当文件描述符收到 I/O 事件通知时,并不知道要处理多少 I/O 数据。

三、内核何时会发送 "IO 就绪" 信号?

对于不同类型的文件描述符,情况不一样。

1> 终端

对于终端,当有新的输入时会会产生信号。

2> 管道和 FIFO

对于读端,下列情况会产生信号:

数据写入到管道中;

管道的写端关闭;

对于写端,下列情况会产生信号:

对管道的读操作增加了管道中的空余空间大小。

管道的读端关闭;

3> 套接字

对于 UDP 套接字,下列情况会产生信号:

数据报到达套接字;

套接字上发生异步错误;

对于 TCP 套接字,信号驱动式 I/O 近乎无用。

太多情况都会产生信号,而我们又无法得知事件类型,因此这里就不再列举其产生信号的情况。

四、最简单的示例

信号处理函数:

staticvolatilesig_atomic_tgotSigio=0; staticvoidhandler(intsig) { gotSigio=1; }

主程序:

intmain(intargc,char*argv[]) { intflags,j,cnt; structtermiosorigTermios; charch; structsigactionsa; intdone; /*Establishhandler*/ sigemptyset(&sa.sa_mask); sa.sa_flags=SA_RESTART; sa.sa_handler=handler; if(sigaction(SIGIO,&sa,NULL)==-1){ perror("sigaction() "); exit(1); } /*Setownerprocess*/ if(fcntl(STDIN_FILENO,F_SETOWN,getpid())==-1){ perror("fcntl()/F_SETOWN "); exit(1); } /*Enable"I/Opossible"signalingandmakeI/Ononblocking*/ flags=fcntl(STDIN_FILENO,F_GETFL); if(fcntl(STDIN_FILENO,F_SETFL,flags|O_ASYNC|O_NONBLOCK)==-1){ perror("fcntl()/F_SETFL "); exit(1); } for(done=0,cnt=0;!done;cnt++){ sleep(1); if(gotSigio){ gotSigio=0; /*Readallavailableinputuntilerror(probablyEAGAIN) orEOF*/ while(read(STDIN_FILENO,&ch,1)>0&&!done){ printf("cnt=%d;read%c ",cnt,ch); done=ch=='#'; } } } exit(0); }

运行效果:

./build/sigio a cnt=0;reada cnt=0;read abc cnt=4;reada cnt=4;readb cnt=4;readc cnt=4;read # cnt=7;read#

该程序会先使能信号驱动 IO,然后循环执行计数操作。

当有 IO 就绪信号到来时,会去终端读取数据并打印出来,然后继续执行计数操作。

五、扩展知识

I/O 多路复用 、信号驱动 I/O 以及 epoll 机制可用于监视多个文件描述符。

它们并不实际执行 I/O 操作,当某个文件描述符处于就绪态,仍需采用传统的 I/O 系统调用来完成 I/O 操作。

相比 I/O 多路复用,当监视大量的文件描述符时信号驱动 I/O 有着显著的性能优势,原因是内核能够帮进程记录了正在监视的文件描述符列表。

信号驱动 I/O 的缺点:

信号的处理流程较为复杂;

无法指定需要监控的事件类型。

Linux 特有的 epoll 是一个更好的选择。

六、相关参考

UNIX 网络编程卷1

6.2 I/O模型

25 信号驱动式I/O

Linux-UNIX 系统编程手册

63 其他备选的I/O模型

Linux 高性能服务器编程

8.3 I/O 模型

Linux 多线程服务端编程_使用muduo C++网络库

7.4.1 muduo的IO模型

编辑:jq

声明:本文内容及配图由入驻作者撰写或者入驻合作网站授权转载。文章观点仅代表作者本人,不代表电子发烧友网立场。文章及其配图仅供工程师学习之用,如有内容侵权或者其他违规问题,请联系本站处理。 举报投诉
  • 驱动
    +关注

    关注

    12

    文章

    1929

    浏览量

    88248

原文标题:3 分钟快速了解信号驱动式 IO

文章出处:【微信号:mcu168,微信公众号:硬件攻城狮】欢迎添加关注!文章转载请注明出处。

收藏 人收藏
加入交流群
微信小助手二维码

扫码添加小助手

加入工程师交流群

    评论

    相关推荐
    热点推荐

    极简XXTEA加密解密:5分钟代码速学!

    XXTEA加密解密的极简实现方法来了!只需5分钟,跟着本文的代码示例学习,就能快速掌握加密与解密的核心技巧,轻松应用到项目中。 XXTEA
    的头像 发表于 11-12 14:49 129次阅读
    极简XXTEA加密解密:5<b class='flag-5'>分钟</b>代码速学!

    UPS选型指南:小白必看!3分钟搞懂在线、后备、互动的区别

    (不间断电源)就是专门解决这个问题的"电力保镖"。但市面上有在线、后备、互动三种UPS,到底该怎么选?今天用大白话+生活类比,3分钟
    的头像 发表于 10-09 08:51 610次阅读
    UPS选型指南:小白必看!<b class='flag-5'>3</b><b class='flag-5'>分钟</b>搞懂在线<b class='flag-5'>式</b>、后备<b class='flag-5'>式</b>、互动<b class='flag-5'>式</b>的区别

    测试小白3分钟上手,零代码自动化测试平台,15分钟搭建自动化测试方案

    还在为不懂代码、搭建测试方案耗时久而发愁?ATECLOUD 零代码自动化测试平台,专为自动化测试量身打造,小白3 分钟就能轻松上手,15 分钟即可完成自动化测试方案搭建,彻底打破传统测
    的头像 发表于 09-22 17:52 635次阅读
    测试小白<b class='flag-5'>3</b><b class='flag-5'>分钟</b>上手,零代码自动化测试平台,15<b class='flag-5'>分钟</b>搭建自动化测试方案

    ADI Trinamic TMC5240评估套件数据手册

    。它的启动快速、简单,只需分钟就能让用户的电机运转,同时提供对所有寄存器、功能和诊断的完全访问。对于诊断,MCU和TMC5240之间的所有信号
    的头像 发表于 06-17 14:12 970次阅读
    ADI Trinamic TMC5240评估套件数据手册

    仿真又不对?看看一流工程师怎么分析!

    可能有人觉得大信号信号要看仿真设置,激励源幅度大就是大信号,激励源幅度小就是小信号。正不正确只需要简单验证一下就好,还是上面的电路,对激励
    的头像 发表于 05-06 16:56 1692次阅读
    仿真又不对?<b class='flag-5'>看看</b>一流工程师怎么分析!

    10分钟上手写代码,LuatOS协程轻松掌握!

    10分钟学会LuatOS协程,从此的程序也能像通勤族利用碎片时间一样游刃有余。现在就去动手试一试,开启异步编程新体验! 写给第一次听说协程的‌: 别怕!协程不是复杂概念,看完这篇,10分钟
    的头像 发表于 04-10 15:18 514次阅读
    10<b class='flag-5'>分钟</b>上手写代码,LuatOS协程轻松掌握!

    不知道的COB封装测试方法,快来看看推拉力测试机的应用!

    近期,有客户向小编咨询推拉力测试机,如何进行COB封装测试?在现代电子制造领域,COB(Chip on Board)封装技术因其高集成度和灵活性被广泛应用于LED、传感器、显示驱动等产品中。然而
    的头像 发表于 04-03 10:42 1262次阅读
    <b class='flag-5'>你</b>不知道的COB封装测试方法,<b class='flag-5'>快来看看</b>推拉力测试机的应用!

    腾讯会议免费40分钟不够用?要的秘诀在这里!

    随着远程工作的普及,视频会议工具成为许多企业和个人的必备选择。然而,像腾讯会议这样的免费版工具,其40分钟的时长限制常常让人头疼——尤其是在需要长时间讨论、培训或协作时,中途断线不仅打断思路,还
    的头像 发表于 03-25 09:24 1654次阅读
    腾讯会议免费40<b class='flag-5'>分钟</b>不够用?<b class='flag-5'>你</b>要的秘诀在这里!

    STM32CubeMx使用ADC时,只需要将通道进行配置,不需要对引脚进行模拟输入吗?

    当使用ADC时,只需要将通道进行配置,不需要对引脚进行模拟输入吗?模拟输入脚只能够接收模拟电压信号,而ADC只是将模拟信号转换为数字信号的,
    发表于 03-13 07:32

    MR30分布式IO模块:驱动智能制造工厂的工业互联与高效控制新范式

    在工业4.0与智能制造浪潮的推动下,传统制造业正经历着从“机械驱动”向“数据驱动”的深刻转型。作为工业数据连接领域的领军者,明达技术凭借其自主研发的MR30分布式IO模块,以创新的技术
    的头像 发表于 02-08 16:01 650次阅读

    为什么嵌入驱动开发工程师可以拿高薪?

    技术领域具有不可替代的地位。 成为一名优秀的嵌入驱动工程师只需要深耕以下几点: 1)坚实的技术基础: 首先,需要有坚实的基础,包括计算机组成原理、微处理器与微控制器架构以及电路设计
    发表于 01-07 16:56

    MR30分布式IO模块助力PLC,打造高效智能仓储系统

    详细介绍如何通过明达技术MR30分布式IO模块配合西门子PLC,实现智能仓储系统中的各种信号采集与控制。
    的头像 发表于 01-03 10:16 776次阅读
    MR30<b class='flag-5'>分布式</b><b class='flag-5'>IO</b>模块助力PLC,打造高效智能仓储系统

    ADS1115接线是只需要接SCL与SDA吗?ADDR与ALERT/RDY需要接线吗?

    ADS1115接线是只需要接SCL与SDA吗?ADDR与ALERT/RDY需要接线吗? 差输入与单输入有什么区别,怎样配置两种模式?
    发表于 12-31 06:27

    AD模数转换器敷铜是AGND和DGND分开敷,还是只需要在顶层和底层敷AGND?

    AD模数转换器敷铜,双面布板,AGND和DGND已通过0欧姆电阻连接好,我想问,敷铜是AGND和DGND分开敷,还是只需要在顶层和底层敷AGND?
    发表于 12-27 08:16

    ADS1246校正是不是只需要发送校正命令就行了?

    第一次作信号测量工作,好多基础的知识不甚了解 ADS1246校正是不是只需要发送校正命令就行了,后面测量模拟信号转换出来的二进制数直接使用就行了吗?这些数据不
    发表于 12-27 06:19