了解Linux的I/O模型

275次阅读  |  发布于2年以前

I/O是input/output的缩写,表示计算机与外接设备之间的数据传输。最常见的I/O类型有磁盘I/O、网络IO。IO和CPU比起来是非常低效的,为了保障应用程序的运行效率,Linux支持多种IO模型。

I/O模型是面试中经常被问到到技术点,也是软件开发过程中经常需要处理到问题。本文主要分析Linux操作系统中I/O模型的分类及各自的特点。我们主要以网络IO为例来分析。

在Linux中常见的I/O模型有:阻塞I/O、非阻塞I/O、多路复用I/O、信号驱动I/O和异步I/O。

阻塞IO

应用程序发起数据请求之后程序一直阻塞,直到数据复制完成。数据复制的过程经过了内核态的数据准备和拷贝到用户空间两个阶段。

非阻塞IO

和阻塞IO相反,应用程序发起请求之后内核态会立刻返回未准备完成的状态给应用程序(不会一直等待数据复制完成)。应用程序通过轮询访问数据,直到数据返回。

多路复用IO

在并发环境下,一秒钟可能有成千上万的请求发送到服务器,不管是堵塞IO还是非堵塞IO模型都需要创建非常多的进程去处理请求。但是创建进程成本巨大,而且跨进程的数据交换也相对复杂。这就诞生了IO复用技术,一个进程就可以服务多个客户端。Linux中实现IO多路复用有三种方式:select、pool、epool。

多路复用的IO模型虽然还是堵塞状态,但好处通过内核提供的select、pool、epool函数可以将多个文件描述符集中统一监控,这就可以极大的减少进程数。 select出现的要比epool早,但是select方法存在比较大的性能问题:

  1. 调用select函数后,需要对所有文件描述符循环监听。
  2. 每次调用select函数都需要传递监视对象信息。 epool函数刚好解决了select的两大问题,性能较好。(1G的内存能监听接近10万个端口号)

信号驱动IO

在信号驱动IO模型中,应用程序和内核首先建立信号处理机制,应用程序继续执行其它任务不会被阻塞,等内核准备好数据之后,通过SINGIO通知应用程序数据准备完成,应用程序再通过系统调用获取数据。

异步IO

前面四种IO模型,第一种堵塞IO是进程完全阻塞,后面的非堵塞IO、多路复用IO、信号驱动IO虽然减少了应用程序阻塞等待的时间,但是都需要应用程序主动发起系统调用读取内核中的数据,所以这四种IO模型都属于同步IO。异步IO模型,没有任何阻塞,应用程序通过系统调用给内核发送一个信号,内核在数据拷贝到用户空间之后通过信号量通知应用程序数据准备完成。

参考资料:《TCP/IP网络编程》

Copyright© 2013-2020

All Rights Reserved 京ICP备2023019179号-8