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

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

3天内不再提示

Linux的5种IO模型

FPGA之家 来源:FPGA之家 作者:FPGA之家 2022-08-12 09:22 次阅读

哈喽,我是老吴,俺又来分享文章啦!

浑浑噩噩到了 30 岁,距离开滴滴还有 5 年的时间。

还有机会全身而退吗?

哈哈!

30 而立,今年会是值得拼搏的一年,干它!

以下是正文:

一、Linux 的 5 种 IO 模型
二、如何使用信号驱动式 I/O?
三、内核何时会发送 "IO 就绪" 信号?
四、最简单的示例
五、扩展知识

一、Linux 的 5 种 IO 模型

阻塞式 I/O:

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

1ad5174c-19db-11ed-ba43-dac502259ad0.png

点击查看大图

非阻塞式 I/O (O_NONBLOCK):

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

1ae66bb4-19db-11ed-ba43-dac502259ad0.png

点击查看大图

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

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

1af9df32-19db-11ed-ba43-dac502259ad0.png

点击查看大图

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

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

1b1c96da-19db-11ed-ba43-dac502259ad0.png

点击查看大图

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

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

1b327766-19db-11ed-ba43-dac502259ad0.png

点击查看大图

思考一下,什么时候应该选择何种 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模型

审核编辑 :李倩



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

    关注

    87

    文章

    10990

    浏览量

    206730
  • 信号处理
    +关注

    关注

    47

    文章

    854

    浏览量

    102523
  • 函数
    +关注

    关注

    3

    文章

    3868

    浏览量

    61308

原文标题:思考技术,也思考人生

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

收藏 人收藏

    评论

    相关推荐

    什么是io多路复用?IO多路复用的优缺点

    IO多路复用是一种同步IO模型,它允许单个进程/线程同时处理多个IO请求。具体来说,一个进程/线程可以监视多个文件句柄,一旦某个文件句柄就绪,就能够通知应用程序进行相应的读写操作。在没
    的头像 发表于 01-18 15:48 796次阅读

    【爱芯派 Pro 开发板试用体验】部署爱芯派官方YOLOV5模型

    继上文开箱后,本文主要依托爱芯元智官方的实例,进行官方YOLOV5模型的部署和测试。 一、环境搭建 由于8核A55的SoC,加上目前Debian OS的工具齐全,所以决定直接在板上编译程序
    发表于 12-12 22:58

    使用系统IO和标准IO的基本原理

    系统 IO 一般指的是 Linux/Unix 系统调用中关于 I/O 操作的统称,其中包括 open、read、write、close 等操作。
    的头像 发表于 11-24 09:48 460次阅读
    使用系统<b class='flag-5'>IO</b>和标准<b class='flag-5'>IO</b>的基本原理

    异步IO框架iouring介绍

    前言 Linux内核5.1支持了新的异步IO框架iouring,由Block IO大神也即Fio作者Jens Axboe开发,意在提供一套公用的网络和磁盘异步IO,不过
    的头像 发表于 11-09 09:30 606次阅读
    异步<b class='flag-5'>IO</b>框架iouring介绍

    linux异步io框架iouring应用

    Linux内核5.1支持了新的异步IO框架iouring,由Block IO大神也即Fio作者Jens Axboe开发,意在提供一套公用的网络和磁盘异步IO,不过
    的头像 发表于 11-08 15:39 269次阅读
    <b class='flag-5'>linux</b>异步<b class='flag-5'>io</b>框架iouring应用

    信号驱动IO与异步IO的区别

    一. 谈信号驱动IO (对比异步IO来看) 信号驱动IO 对比 异步 IO进行理解 信号驱动IO: 内核将数据准备好的时候, 使用SIGIO
    的头像 发表于 11-08 15:32 386次阅读
    信号驱动<b class='flag-5'>IO</b>与异步<b class='flag-5'>IO</b>的区别

    RK3568外部IO中断示例

    ​外部IO中断介绍本篇文章以万象奥科HD-RK3568-IOT评估板中GPIO30为例,介绍Linux内核中断的注册方法,使用中断的方式检测GPIO30是否出现上升沿信号。中断在linux、设备驱动
    的头像 发表于 11-03 13:56 580次阅读
    RK3568外部<b class='flag-5'>IO</b>中断示例

    多路IO复用模型和异步IO模型介绍

    多路 IO 复用模型 多路 IO 复用,有时也称为事件驱动 IO。它的基本原理就是有个函数会不断地轮询所负责的所有 socket ,当某个 socket有数据到达了,就通知用户进程。
    的头像 发表于 10-08 17:21 507次阅读
    多路<b class='flag-5'>IO</b>复用<b class='flag-5'>模型</b>和异步<b class='flag-5'>IO</b><b class='flag-5'>模型</b>介绍

    网络IO模型:阻塞与非阻塞

    阻塞 IO 模型Linux ,默认情况下所有的 socket 都是阻塞的,一个典型的读操作流程如图所示。 阻塞和非阻塞的概念描述的是用户线程调用内核 IO 操作的方式:阻塞是指
    的头像 发表于 10-08 17:16 484次阅读
    网络<b class='flag-5'>IO</b><b class='flag-5'>模型</b>:阻塞与非阻塞

    IO如何实现

    。为了提供系统吞吐量, 降低硬件资源的开销,IO模型也在不断适应大规模、高并发需求不断演进,今天我们就来看看这个在网络上高频出现的词汇 IO模型 l
    的头像 发表于 09-25 10:57 509次阅读
    <b class='flag-5'>IO</b>如何实现

    keras顺序模型与函数式模型

    keras提供两搭建模型的方式: 1. 顺序模型(也可看做是函数式模型的一特殊情况) 2. 函数式
    发表于 08-18 06:01

    如何使用DS-5 1.0版调试Linux应用程序

    的Cortex-A9固定虚拟平台(FVP)模型上加载该应用程序。 DS-5附带Cortex-A9固定虚拟平台(FVP)型号
    发表于 08-12 06:01

    查看linux系统磁盘io情况的办法是什么

    谈到 Linux 磁盘 I/O 的工作原理,我们了解到 Linux 存储系统 I/O 栈由文件系统层(file system layer)、通用块层( general block layer)和设备层(device layer)构成。
    发表于 08-01 10:14 1850次阅读

    嵌入式Linux学习笔记:文件IO

    linux中一切都叫文件,比如普通文件,设备文件,管道。在应用层,可以用一套文件IO读写文件,其实就是一套能够操作文件的系统调用。文件IO又称为不带缓存的IO,因为文件
    发表于 06-23 14:25 162次阅读
    嵌入式<b class='flag-5'>Linux</b>学习笔记:文件<b class='flag-5'>IO</b>

    Linux驱动学习笔记:异步IO

    前几篇介绍了几种IO模型,今天介绍另一种IO模型——异步IO
    发表于 06-12 16:24 478次阅读