电子工程师技术服务社区
公告
登录
|
注册
首页
技术问答
厂商活动
正点原子
板卡试用
资源库
下载
文章
社区首页
文章
【i.MX6ULL】驱动开发9——Linux IO模型分析
分 享
扫描二维码分享
【i.MX6ULL】驱动开发9——Linux IO模型分析
i.MX6ULL
嵌入式
linux
码农爱学习
关注
发布时间: 2021-12-08
丨
阅读: 644
前面两篇介绍按键的文章,无论是用GPIO来读取,还是用中断的方式,其应用程序通过循环读取的方式获取按键值,都会使得CPU的占用率很高。本篇先来介绍Linux中几种的I/O模型,以后使用这类方式进行按键值的读取,可以极大降低CPU的使用率。 # 1 Linux中的I/O模型 这里以网络I/O为例进行分析,网络IO的本质是socket的读取,socket在linux系统被抽象为流,对于一次IO访问,以read为例,当一个read操作发生时,它会经历两个阶段: - 等待数据准备 (Waiting for the data to be ready) - 将数据从内核拷贝到进程中 (Copying the data from the kernel to the process) 网络I/O的模型,可以分为五种,这里先分类列出: ![](https://cf05.ickimg.com/bbsimages/202111/bf03a684f044d178ab1046c90b96d64c.png) # 2 五种I/O模型分析 ## 2.1 阻塞式I/O模型 阻塞式I/O模型是最常用、最简单的模型。阻塞就是进程被休息, CPU处理其它进程去了。 应用程序进行recefrom系统调用,操作系统收到recefrom系统调用请求,经过两个阶段: - 等待数据准备好 - 内核将数据从内核缓冲区复制到用户缓冲区 这两个阶段完成后调用返回,应用程序**解除阻塞**。 ![](https://cf05.ickimg.com/bbsimages/202111/5c4440af95d61d5d9d2724d62b7c6321.png) ## 2.2 非阻塞式I/O模型 非阻塞就是轮询的方式,在这种模型中, I/O操作不会立即完成,recefrom操作可能会返回一个错误代码,说明这个命令不能立即满足。 对于第一个阶段: - 等待数据准备好 在这个阶段系统调用会立刻返回一个错误状态,**不会阻塞**,应用程序需要不断轮询,直到内核缓冲区数据准备好 对于第二个阶段: - 内核将数据从内核缓冲区拷贝到用户缓冲区 这个阶段应用程序的调用**会被阻塞**,直到拷贝完成,应用程序的系统调用返回。 ![](https://cf05.ickimg.com/bbsimages/202111/9aa3186f1d7758156c4e94c4b15d6a76.png) ## 2.3 I/O复用模型 由于非阻塞I/O方式需要不断轮询,会消耗大量的CPU时间,而后台又可能有多个任务在同时轮询,为此,人们就想到了一种方式:**循环查询多个任务**的完成状态,只要有任何一个任务完成,就去处理它。 IO多路复用有两个特别的系统调用**select、poll**。 select可以等待多个socket,能实现同时对多个IO端口进行监听,当其中任何一个socket的数据准好了,就能返回进行可读,然后进程再进行recvform系统调用,将数据由内核拷贝到用户进程,这个过程是阻塞的。 ![](https://cf05.ickimg.com/bbsimages/202111/046371002e5b5638ff384ad8796dea45.png) ## 2.4 信号驱动式I/O模型 应该程序进行Read系统调用,进程继续运行不会阻塞,立即返回,等待内核缓冲区数据准备好后,通过SIGIO信号通知应用程序,应用程序再进行Read系统调用,内核将内核缓冲区中的数据拷贝到用户缓冲区,调用完成。 ![](https://cf05.ickimg.com/bbsimages/202111/3c3e30962e4f56e9269f7f5429a41947.png) ## 2.5 异步I/O模型 相对于同步IO,异步IO不是顺序执行。用户进程进行aio_read系统调用之后,无论内核数据是否准备好,都会直接返回给用户进程,然后用户态进程可以去做别的事情。等到socket数据准备好了,内核直接复制数据给进程,然后从内核向进程发送通知。**IO两个阶段,进程都是非阻塞的**。 ![](https://cf05.ickimg.com/bbsimages/202111/d48b2a631146b71a65bd0bfe75c635ec.png) # 3 模型对比 ## 3.1 阻塞I/O与非阻塞I/O对比 简单理解为需要做一件事能不能立即得到返回应答,如果不能立即获得返回,需要等待,那就阻塞了,否则就可以理解为非阻塞。详细区别如下图所示: ![](https://cf05.ickimg.com/bbsimages/202111/c1800843bea77ce7fc2ffb5e5ea4bd6b.png) ## 3.2 同步I/O与异步I/O对比 实际上同步与异步是针对**应用程序**与**内核**的交互而言的。 - **同步过程**中进程触发IO操作并等待或者轮询的去查看IO操作是否完成。 - **异步过程**中进程触发IO操作以后,直接返回,做自己的事情,IO交给内核来处理,完成后内核通知进程IO完成。 同步与异步如下图所示: ![](https://cf05.ickimg.com/bbsimages/202111/78fd5f0fa18ea82675effae4fe0ac1b6.png) 对于Liunx的五种I/O模型,其实主要在**等待数据和数据复制**这两个时间段不同。 ![](https://cf05.ickimg.com/bbsimages/202111/7630f59881355796eb4dd79feef401a3.png) # 4 各种I/O模型的生活场景式类比 ## 4.1 类比1-饭店点菜 ![](https://cf05.ickimg.com/bbsimages/202111/461cff8707d2c55e189a8b5ea416433f.png) 我们去餐厅吃饭,会经过以下几个步骤:首先根据菜单点菜,然后等待厨房准备好,接着服务员上菜。在这个场景中,等待厨房准备菜肴等同于等待数据,服务员上菜等同于将数据从内核复制到用户空间,你就是用户态进程了,服务员和饭店看作是内核态的进程。 - **阻塞式I/O模型**:只点一个菜,然后在餐桌上开始等待,在这个过程中什么事都不干,等服务员把菜上到桌子上之后才开始大快朵颐。 - **非阻塞式I/O模型**:只点一个菜,然后开始等待,啥事都不做,等了一会儿然后就去问服务员,“我的菜好了吗?”,没好接着等待,过了一会儿然后又跑去问....重复这个过程,直到服务员说“亲,你的菜好了,我现在给您送桌上去”,然后你坐在桌子上,等待服务员把饭菜送到你的餐桌上,才开始吃饭。 - **I/O复用模型**:你点了很多菜,然后开始等待,某个时刻其中一个菜或者多个菜厨房里同时好了,服务员跑过来说,“亲,您的有些菜好了,要现在上桌么?”, 你回答,现在就上,于是服务员上一个菜(服务员一次只能上一个菜),你就吃完一个,上一个你就吃完一个。。。 - **信号驱动式I/O模型**:只点一个菜,然后给服务员留下手机,告诉他菜准备好了打个电话给你,先不要上菜,然后你就出去玩耍了,等到菜好了,服务员手机通知你,你立马回到了餐厅,对服务员说“你现在可以上菜了”,于是你在餐桌上等待服务员把菜送上来,然后吃饭。 - **异步I/O模型**:只点一个菜,然后给服务员留下手机,告诉他菜准备好了先上菜,菜上桌了打电话给你,然后你就出去玩耍了,等到菜上桌了,服务员手机通知你,你立马回到了餐桌,开始吃饭。 该例子出自:
## 4.2 类比2-钓鱼 ![](https://cf05.ickimg.com/bbsimages/202111/5c1301cb09bda0fc0cbca509c512d499.png) 有A,B,C,D四个人在钓鱼。 - **阻塞式I/O模型**:A用的是最老式的鱼竿,所以呢,得一直守着,等到鱼上钩了再拉杆; - **非阻塞式I/O模型**:B的鱼竿有个功能,能够显示是否有鱼上钩,所以呢,B就和旁边的MM聊天,隔会再看看有没有鱼上钩,有的话就迅速拉杆; - **I/O复用模型**:C用的鱼竿和B差不多,但他想了一个好办法,就是同时放好几根鱼竿,然后守在旁边,一旦有显示说鱼上钩了,它就将对应的鱼竿拉起来; - **异步I/O模型**:D是个有钱人,干脆雇了一个人帮他钓鱼,一旦那个人把鱼钓上来了,就给D发个短信。 该例子出自:
## 4.3 类比3-银行存钱汇款 ![](https://cf05.ickimg.com/bbsimages/202111/83fa1ee63b69fdc89ed07b3e6ac36e67.png) - **阻塞式I/O模型**:你去一个银行柜台存钱。首先,你会将存钱的单子填好,交给柜员,之后,你就坐在柜台前等。柜员办好以后会给你一个回执,表示办好了,然后你就可以拿着回执干其它的事了。注意,这时如果你马上去查账,存的钱已经打到你的账户上了。 - **非阻塞式I/O模型**:这次不是去银行存钱,而是去银行汇款。同样的,你也需要填写汇款单然后交给柜员,柜员进行一些简单的手续处理就能够给你回执。但是,你拿到回执并不意味着钱已经打到了对方的账上。事实上,一般汇款的周期大概是24个小时左右,如果你要以存钱的模式来汇款的话,意味着你需要在银行等24个小时,这显然是不现实的。 - **I/O复用模型**:比如说一个银行柜台,现在有10个人想存钱。这10个人都填好存款单,然后都提交给柜台,提交完之后所有的10个人就在银行大厅等待。这时候会专门有个人,他会了解存款单处理的情况,一旦有存款单处理完毕,他会将回执交给相应的正在大厅等待的人,这个拿到回执的人就可以去干其他的事情了。而前面提到的这个专人,就对应于select函数。 - **异步I/O模型**:现在某银行新开通了一项存钱业务。用户之需要将存款单交给柜台,然后无需等待就可以离开了。柜台办好以后会给用户发送一条短信,告知交易成功。这样用户不需要在柜台前进行长时间的等待,同时,也能够得到确切的消息知道交易完成。 该例子出自:
# 5 总结 本篇介绍了Linux中的五种I/O模型:阻塞式I/O模型、非阻塞式I/O模型、I/O复用模型、信号驱动式I/O模型、异步I/O模型,并通过生活中实际的场景进来类比。
原创作品,未经权利人授权禁止转载。详情见
转载须知
。
举报文章
点赞
(
0
)
码农爱学习
关注
评论
(1)
登录后可评论,请
登录
或
注册
焉焉女侠
132
天前...
xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx
0
回复
发布
相关文章推荐
MK-米客方德推出工业级存储卡
Beetle ESP32 C3 蓝牙数据收发
Beetle ESP32 C3 wifi联网获取实时天气信息
开箱测评Beetle ESP32-C3 (RISC-V芯片)模块
正点原子数控电源DP100测评
DP100试用评测-----开箱+初体验
Beetle ESP32 C3环境搭建
【花雕体验】16 使用Beetle ESP32 C3控制8X32位WS2812硬屏之二
X
你的打赏是对原创作者最大的认可
请选择打赏IC币的数量,一经提交无法退回 !
100IC币
500IC币
1000IC币
自定义
IC币
确定
X
提交成功 ! 谢谢您的支持
返回
我要举报该内容理由
×
广告及垃圾信息
抄袭或未经授权
其它举报理由
请输入您举报的理由(50字以内)
取消
提交