I/O流
- 概念
(1)c++中将数据的输入输出称之为流(stream),在c++中,流被定义为类,成为流类(stream class),其定义的对象为流对象。
(2)文件,套接字(socket),管道(pipe)等能够进行I/O操作的对象,可以被看做为流
- 工作机制
(1)大多数文件系统的默认I/O操作都是缓存I/O。在Linux的缓存I/O机制中,读取数据时,都会将数据先拷贝到操作系统内核的缓冲区中,然后将操作系统内核缓冲区的数据拷贝到应用程序的地址空间,写的过程则相反。
(2)缓存I/O使用操作系统内核缓冲区,在一定程度上分离了应用程序空间和实际的物理设备,通过将数据写入缓冲区后,再一次性处理,减少了读盘的次数,从而提高了性能
I/O模型
- 同步与异步:关注的是消息通信机制
同步(synchronous):调用者会一直“等待”被调用者返回消息,才能继续执行,在此期间,调用者不能做其它事
异步(asynchronous):被调用者通过状态、通知或回调机制主动通知调用者被调用者的运行状态,在此期间,调用者可以边“等待”,边做其它事
- 阻塞和非阻塞:关注调用者的状态
阻塞(blocking):调用者一直“等待”所处的状态
非阻塞(blocking):调用者能够边“等待”,边做其它事的状态
- 同步I/O
(1)阻塞式I/O:程序发出I/O请求,如果内核缓冲区为空,此时进行读操作,那么该程序就会阻塞
(2)非阻塞式I/O:程序发出I/O请求,如果内核缓冲区为空,此时进行读操作,此时就会立刻返回一个错误
(3)I/O复用
a. 这是一种机制,程序注册一组文件描述符给操作系统,监视多个描述符,一旦某个描述符就绪(一般是读就绪或者写就绪),能够通知程序进行相应的读写操作。表示“我要监视这些fd是否有I/O事件发生,有了就告诉程序处理”。
b. 当多个I/O流共用一个等待机制时,该模型会阻塞进程,但是进程时阻塞在这种机制的系统调用上,不是阻塞在真正的I/O操作上
c. I/O多路复用需要和非阻塞I/O一起使用,非阻塞I/O和I/O多路复用式相对独立的。非阻塞I/O仅仅指流对象立刻返回,不会被阻塞;而I/O多路复用只是操作系统提供的一种便利的通知机制。
(4)信号驱动式I/O
a. 用户进程可以通过系统调用注册一个信号处理程序,然后主程序可以继续向下执行,当有I/O操作准备就绪时,由内核通知触发一个SIGIO信号处理程序执行,然后将用户进程所需要的数据从内核空间拷贝到用户空间
b. 此模型的优势在于等待数据报到达期间进程不被阻塞。用户主程序可以继续执行,只要等待来自信号处理函数的通知。
- 异步I/O
a. 程序进程向内核发送I/O调用后,不用等待内核响应,可以继续接受其他请求,内核调用的I/O如果不能立即返回,内核会继续处理其他事物,直到I/O完成后将结果通知给内核
b. 信号驱动式IO是由内核通知我们何时启动一个IO操作,而异步IO是由内核通知我们IO操作何时完成。
I/O复用模型
- select
select的大致工作流程:
(1)采用数组组织文件描述符
(2)通过遍历数组的方式,监视文件描述符的状态(可读,可写,异常)
(3)如果没有可读/可写的文件描述符,进程会阻塞等待一段事件,超时就返回
(4)当有一个可读/可写的文件描述符存在时,进程会从阻塞状态醒来
(5)进行无差别轮询,找出能够操作的I/O流,若处理后,会移除对应的文件描述符
select的缺点:
(1)每次调用select,都需要把文件描述符集合从用户空间贝到内核空间,这个开销在I/O流很多时会很大
(2)同时每次调用select都需要在内核遍历传递进来的所文件描述符数组,这个开销在I/O流很多时也很大
(3)select支持的文件描述符数量太小了,默认是1024
- poll
(1)采用链表组织文件描述符
(2)原理和select一致
(3)只是解决了支持的文件描述符受限的缺点
(4)select和poll都是水平触发:找到可操作的I/O流并通知进程,但进程本次没有处理,文件描述符没有被移除,下次轮询时依旧会通知
- epoll
工作原理:
(1)红黑树和就绪链表,红黑树用于管理所有的文件描述符,就绪链表用于保存有事件发生的文件描述符。
(2)接收到I/O请求,会在红黑树查找是否存在,不存在就添加到红黑树中,存在则将对应的文件描述符放入就绪链表中
(3)如果就绪链表为空,进程则阻塞否则遍历就绪链表,并通知应用进程处理文件描述符对应的I/O
工作模式:
(1)LT模式(水平触发):检测到可处理的文件描述符时,通知应用程序,应用程序可以不立即处理该事件。后续会再次通知
(2)ET模式(边缘触发):检测到可处理的文件描述符时,通知应用程序,应用程序必须立即处理该事件。如果本次不处理,则后续不再通知
参考资料
IO五种模型和select与epoll工作原理(引入nginx) - osc_1ont5xz2的个人空间 - OSCHINA - 中文开源技术交流社区
IO模型:同步、异步、阻塞、非阻塞 | 神奕的博客 (songlee24.github.io)
(3) io复用与epoll模型详解_个人文章 - SegmentFault 思否
(3) Linux IO模式及 select、poll、epoll详解_人云思云 - SegmentFault 思否
Linux 网络编程的5种IO模型:多路复用(select/poll/epoll) - 黄树超 - 博客园 (cnblogs.com)
(3) 网络编程——select模型(总结)_个人文章 - SegmentFault 思否
网络编程之IO模型与Epoll - 简书 (jianshu.com)