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

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

3天内不再提示

Linux中如何使用信号驱动式I/O?

FPGA之家 来源:嵌入式Hacker 作者:嵌入式Hacker 2021-03-12 14:47 次阅读
加入交流群
微信小助手二维码

扫码添加小助手

加入工程师交流群

一、Linux 的 5 种 IO 模型

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

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

四、最简单的示例

五、扩展知识

一、Linux 的 5 种 IO 模型

阻塞式 I/O:

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

afa36cae-82f4-11eb-8b86-12bb97331649.png

点击查看大图

非阻塞式 I/O (O_NONBLOCK):

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

afe56582-82f4-11eb-8b86-12bb97331649.png

点击查看大图

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

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

b233d076-82f4-11eb-8b86-12bb97331649.png

点击查看大图

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

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

b285771e-82f4-11eb-8b86-12bb97331649.png

点击查看大图

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

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

点击查看大图

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

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

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

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

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

通过 sigaction() 来完成:

int sigaction(int signum, const struct sigaction *act, struct sigaction *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 近乎无用。

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

四、最简单的示例

信号处理函数:

static volatile sig_atomic_t gotSigio = 0; static void handler(int sig) { gotSigio = 1; }

主程序:

int main(int argc, char *argv[]) { int flags, j, cnt; struct termios origTermios; char ch; struct sigaction sa; int done; /* Establish handler */ sigemptyset(&sa.sa_mask); sa.sa_flags = SA_RESTART; sa.sa_handler = handler; if (sigaction(SIGIO, &sa, NULL) == -1) { perror(“sigaction() ”); exit(1); } /* Set owner process */ if (fcntl(STDIN_FILENO, F_SETOWN, getpid()) == -1) { perror(“fcntl() / F_SETOWN ”); exit(1); } /* Enable “I/O possible” signaling and make I/O nonblocking */ 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; /* Read all available input until error (probably EAGAIN) or EOF */ while (read(STDIN_FILENO, &ch, 1) 》 0 && !done) { printf(“cnt=%d; read %c ”, cnt, ch); done = ch == ‘#’; } } } exit(0); }

运行效果:

。/build/sigio a cnt=0; read a cnt=0; read abc cnt=4; read a cnt=4; read b cnt=4; read c 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++网络库

原文标题:Linux-C 编程 | 3 分钟快速了解信号驱动式 IO

文章出处:【微信公众号:FPGA之家】欢迎添加关注!文章转载请注明出处。

责任编辑:haq

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

    关注

    88

    文章

    11627

    浏览量

    217888
  • 信号
    +关注

    关注

    11

    文章

    2901

    浏览量

    79652

原文标题:Linux-C 编程 | 3 分钟快速了解信号驱动式 IO

文章出处:【微信号:zhuyandz,微信公众号:FPGA之家】欢迎添加关注!文章转载请注明出处。

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

扫码添加小助手

加入工程师交流群

    评论

    相关推荐
    热点推荐

    飞凌嵌入ElfBoard-文件I/O的深入学习之异步I/O

    I/O多路复用,进程通过系统调用select或poll来主动查询文件描述符上是否可以执行I/O操作。而在异步
    发表于 12-05 11:23

    飞凌嵌入ElfBoard-文件I/O的深入学习之I/O多路复用

    程序既要读取鼠标、又要读取键盘,多路读取。可以采用两个功能几乎相同的系统调用来执行I/O多路复用操作,分别是系统调用select和poll(当然两者存在相同的一个缺点就是,当包含大量文件描述符的数组
    发表于 12-05 11:18

    飞凌嵌入ElfBoard-文件I/O的深入学习之阻塞I/O与非阻塞I/O

    1.4.1.1 概念 阻塞I/O顾名思义就是对文件的I/O操作是阻塞的,即假如对某些类型文件(管道文件、网络设备文件和字符设备文件)进行读
    发表于 12-01 13:07

    飞凌嵌入ElfBoard-文件I/O的了解探究之I/O缓冲

    返回。如果在此期间,其它进程调用read函数读取该文件的这几个字节数据,那么内核将自动从缓冲区读取这几个字节数据返回给应用程序。这样的设计,目的是为了提高文件I/O的速度和效率,使得系统调用read
    发表于 11-19 16:24

    浅谈光学I/O模块的热挑战

    服务器和机架式网络基础设施系统内的光学 I/O 模块通常接受主动冷却系统的直接冷却,特别是来自机架式设备前面板的强制风冷。机架式设备的散热设计需要平衡 I/O 模块的热管理与处理器或
    的头像 发表于 11-03 09:32 428次阅读
    浅谈光学<b class='flag-5'>I</b>/<b class='flag-5'>O</b>模块的热挑战

    MR30分布I/O助力物流分拣系统智能化升级

    本文以MR30分布I/O在某大型电商物流中心分拣系统的应用为例,详细阐述其在合流、分拣、分流、分运全流程的模块化应用方案。
    的头像 发表于 10-31 10:58 884次阅读
    MR30分布<b class='flag-5'>式</b><b class='flag-5'>I</b>/<b class='flag-5'>O</b>助力物流分拣系统智能化升级

    MR30系列分布I/O在造型机产线的应用

    ,该公司在最新一代造型机生产线引入明达技术MR30系列分布I/O,通过分布信号采集与控制,
    的头像 发表于 10-30 14:02 406次阅读
    MR30系列分布<b class='flag-5'>式</b><b class='flag-5'>I</b>/<b class='flag-5'>O</b>在造型机产线的应用

    飞凌嵌入ElfBoard-系统应用编程之文件I/O

    1.1 文件I/O的简单概念本章节仅作为初识简单概念,在后续章节会对相关概念进行深入介绍。在linux系统中有一个概念,一切皆文件,所有的设备都以文件形式存在。几乎所有的设备、资源都以文件的形式进行
    发表于 10-24 08:57

    MR30分布I/O模块在涂装产线的应用

    某装备制造企业主要从事自动化焊割、涂装生产线的设计与制造,其中涂装生产线涉及喷砂、喷漆、热处理、废气处理等工艺。明达技术的MR30系列分布I/O,性能稳定,易上手,方便接线,助力企业提升产品
    的头像 发表于 08-27 15:38 424次阅读
    MR30分布<b class='flag-5'>式</b><b class='flag-5'>I</b>/<b class='flag-5'>O</b>模块在涂装产线<b class='flag-5'>中</b>的应用

    MAX7325 I²C端口扩展器,提供8路推挽I/O和8个漏极开路I/O技术手册

    MAX7325 2线串行接口外设具有16路I/O端口。其中8路为推挽输出,另外8路为I/O端口,带有可选择的内部上拉和瞬态检测功能。8路I/
    的头像 发表于 05-22 15:27 668次阅读
    MAX7325 <b class='flag-5'>I</b>²C端口扩展器,提供8路推挽<b class='flag-5'>式</b><b class='flag-5'>I</b>/<b class='flag-5'>O</b>和8个漏极开路<b class='flag-5'>I</b>/<b class='flag-5'>O</b>技术手册

    简仪科技高性能PXI模拟I/O模块JY-951概述

    JY-9511 是一款专为动态测量环境精密数据采集与信号生成设计的高性能 PXI 模拟 I/O 模块。
    的头像 发表于 05-09 16:33 727次阅读

    嵌入学习-飞凌嵌入ElfBoard ELF 1板卡-I2C设备驱动Linux下的I2C驱动简介

    的通信协议,其中一个设备作为主设备控制总线,并与多个从设备通信。在Linux内核I2C驱动主要由三部分组成:I2C核心、
    发表于 04-15 10:39

    I/O接口与I/O端口的区别

    在计算机系统I/O接口与I/O端口是实现CPU与外部设备数据交换的关键组件,它们在功能、结构、作用及运作机制上均存在显著差异,却又相互协
    的头像 发表于 02-02 16:00 2787次阅读

    迅为RK3568开发板驱动指南Linux通用SPI设备驱动

    迅为RK3568开发板驱动指南Linux通用SPI设备驱动
    的头像 发表于 01-23 11:02 3416次阅读
    迅为RK3568开发板<b class='flag-5'>驱动</b>指南<b class='flag-5'>Linux</b><b class='flag-5'>中</b>通用SPI设备<b class='flag-5'>驱动</b>

    分布 I/O 配合高冗余 PLC,打造高效控制新典范

    在当今工业自动化领域,高效且稳定的控制解决方案始终是企业追求的目标。而分布 I/O 与高冗余 PLC 的完美配合,正如同强强联合的双子星,为工业生产带来了前所未有的高效控制体验,助力企业在激烈的市场竞争
    的头像 发表于 12-27 17:40 782次阅读
    分布<b class='flag-5'>式</b> <b class='flag-5'>I</b>/<b class='flag-5'>O</b> 配合高冗余 PLC,打造高效控制新典范