当前位置: 代码网 > 服务器>服务器>Linux > Linux五种IO模型的使用解读

Linux五种IO模型的使用解读

2025年09月23日 Linux 我要评论
最近一直在研究linux io模型,linux io模型是一个挺复杂的概念,分析linux io模型一定要注意方法,否则会在一个个概念中,迷失自我。1.io模型简介linux io模型是指linux操

最近一直在研究linux io模型,linux io模型是一个挺复杂的概念,分析linux io模型一定要注意方法,否则会在一个个概念中,迷失自我。

1.io模型简介

linux io模型是指linux操作系统中用于实现输入输出的一种机制。

linux io模型主要分为五种:

阻塞io、非阻塞io、io复用、信号驱动io和异步io。

  • 阻塞io是最常见的io模型,当用户进程发起一个io请求后,内核会一直等待,直到io操作完成并返回结果。在此期间,用户进程会被阻塞,无法进行其他操作。
  • 非阻塞io是在阻塞io的基础上进行改进的一种io模型。当用户进程发起一个io请求后,内核会立即返回一个错误码,表示io操作还未完成。用户进程可以继续进行其他操作,随后再通过轮询的方式来查询io操作是否完成。
  • io复用是指通过select、poll、epoll等系统调用来监听多个文件描述符的io事件。当某个文件描述符就绪时,内核会通知用户进程进行io操作。相比于阻塞io和非阻塞io,io复用可以同时监听多个文件描述符,提高了io效率。
  • 信号驱动io是指用户进程通过signal或sigaction系统调用来注册一个信号处理函数,当io操作完成时,内核会向用户进程发送一个sigio信号,用户进程在信号处理函数中进行io操作。相比于阻塞io和非阻塞io,信号驱动io可以避免用户进程被阻塞,提高了io效率。
  • 异步io是指当用户进程发起一个io请求后,内核会立即返回,表示io操作已经开始。当io操作完成后,内核会通知用户进程,用户进程在此时才进行io操作。相比于其他io模型,异步io可以避免用户进程被阻塞,提高了io效率。

2.五种io模型

2.1 io模型分析方法

分析io模型需要了解2个问题:

问题1:发送io请求,io请求可以理解为用户空间和内核空间数据同步,根据发起者不同分为以下两种情况:

  • 由用户程序发起(同步io)。
  • 由内核发起(异步io)。

问题2:等待数据到来,等待数据到来的方式有以下几种:

  • 阻塞(阻塞io)。
  • 轮询(非阻塞io)。
  • 信号通知(信号驱动io)。

(内核空间和用户空间数据同步由谁发起是分析linux io模型最核心问题)

2.2 阻塞io

阻塞io/阶段1

  • 用户程序调用recv函数发起io请求(同步io),读取socket缓冲区数据。
  • 由于socket缓冲区没有就绪数据包,进程状态将从task_running切换至task_interruptible状态,并通过进程调度完成进程阻塞。
  • 同时进程也会加入到socket等待队列,等待数据到来回被唤醒。

注意:阻塞io并不是阻塞cpu,而是进行进程状态切换出让cpu。

阻塞io/阶段2

  • 网卡收到数据包后,通过dma机制将数据包拷贝到内核空间ringbuffer,并通过中断机制将数据包拷贝至socket接收缓冲区.
  • socket接收到数据包唤醒等待队列休眠进程,进程被唤醒后继续完成用户空间和内核空间数据同步,recv函数成功返回。

2.3 非阻塞io

阻塞io/阶段1

  • 用户程序调用recv函数发起io请求,读取socket缓冲区数据。
  • 由于socket缓冲区没有就绪数据包,非阻塞io recv直接返回ewouldblock错误码,用户如果一直调用recv函数则一直返回ewouldblock错误码,直到数据准备好。

非阻塞io/阶段2

非阻塞io和阻塞io阶段2相同。

2.4 io复用

io复用简介

io复用是一种高效的io处理方式,它可以让一个进程同时监视多个文件描述符,当其中任意一个文件描述符就绪时,就可以进行相应的io操作。

相比于传统的阻塞io和非阻塞io,io复用可以大大提高io效率,减少cpu资源的浪费。

在linux中,常用的io复用模型有select、poll、epoll等。

io复用模型io请求由用户程序发起,所以io复用模型为同步io。

2.4.1 io复用select模型

select模型通过位图实现io复用,将socket注册到读,写,或异常位图,通过select系统调用轮询位图,获取socket事件,成功获取到socket事件后,select成功返回,此时可以通过接收函数读取socket缓冲区数据。

2.4.2 io复用poll模型

poll模型和select非常相似,主要区别为poll模型把位图改成链表,poll通过链表实现io复用,将socket注册poll_list链表,通过poll系统调用轮询链表,获取socket事件,成功获取到socket事件后,poll成功返回,此时可以通过接收函数读取socket缓冲区数据。

2.4.3 io复用epoll模型

epoll模式采用回调方式获取就绪socket事件,相比于select和poll模型的轮询方式效率更高,通过epoll_ctl系统调用注册socket事件至红黑树,当socket接收到数据后通过回调函数将socket事件添加至就绪队列,调用epoll_wait查询就绪队列就能获取到socket事件。

2.5 信号驱动io

信号驱动io是基于sigio信号实现。

信号驱动io主要由三个步骤组成:

  • 步骤1:用户程序注册sigio处理函数。
  • 步骤2:内核收到数据后,发送sigo信号,执行sigo信号处理函数。
  • 步骤3:用户程序调用recv函数发起io请求,完成用户空间和内核空间数据同步。

信号驱动io是由用户程序发起io请求,所以信号驱动io属于同步io。

2.6 异步io

异步io实现的方式有很多种,上图以poisx aio为例讲解异步io。

分析异步io我们得抓住本质,异步io的io请求由内核发起,只要满足这一个点就是异步io,不管是阻塞或者轮询,或者信号通知,都不影响异步io这个性质。

3.io模型常见问题?

问题1:阻塞io和非阻塞io区别?

a.阻塞io

阻塞io在没有数据包时,会通过阻塞进程等待数据到来,阻塞进程方法为:

  • 设置进程状态为task_interruptible。
  • 通过进程调度切换进程,实现进程阻塞。

进程阻塞期间不会占用cpu资源。

b.非阻塞io

非阻塞io在没有数据包时,通过轮询方式等待数据包到来,没有数据包到来,调用接收函数会立即返回ewouldblock错误码,一直调用接收函数,一直返回ewouldblock错误码。

非阻塞方式采用轮询方式会一直占用cpu资源。

问题2:同步io和异步io区别?

区别同步io和异步io方法很简单,就是用户空间和内核空间数据同步由谁发起。

  • 由用户程序发起则是同步io。
  • 由内核发起则是异步io。

问题3:信号驱动io和异步io区别?

信号驱动io和异步io虽然实现流程有很多相似的地方,比如:注册信号处理函数,发送通知信号,不会阻塞进程等。

信号驱动io和异步io有以下几点区别:

  • 信号驱动io属于同步io。
  • 信号驱动io发送信号通知用户程序发起io请求。
  • 异步io发送信号通知用户程序io请求已由内核发起并完成。

问题4:非阻塞io是不是异步io?

很多同学经常把非阻塞io和异步io关联在一起,其实这个是很错误的一个想法,同步io和异步io都可能会阻塞进程,同步io和异步io本质区别为用户空间和内核空间数据同步由谁发起。

非阻塞io的io请求由用户程序发起,属于同步io。

总结

以上为个人经验,希望能给大家一个参考,也希望大家多多支持代码网。

(0)

相关文章:

版权声明:本文内容由互联网用户贡献,该文观点仅代表作者本人。本站仅提供信息存储服务,不拥有所有权,不承担相关法律责任。 如发现本站有涉嫌抄袭侵权/违法违规的内容, 请发送邮件至 2386932994@qq.com 举报,一经查实将立刻删除。

发表评论

验证码:
Copyright © 2017-2025  代码网 保留所有权利. 粤ICP备2024248653号
站长QQ:2386932994 | 联系邮箱:2386932994@qq.com