Linux I/O模型简介
1、基本概念
在进行网络编程时,我们常常见到同步(Sync)、异步(Async),阻塞(Block)、非阻塞(Unblock)四种调用方式。
- 同步:调用一个功能,该功能没有结束前,一直等待。
- 异步:调用一个功能,不需要知道该功能结果,该功能有结果后通知我(回调通知)。
- 阻塞:调用函数,函数没有接收完数据或者没有得到结果之前,不会返回。
- 非阻塞:调用我函数,函数立即返回,通过select通知调用者。
2、Linux I/O模型
2.1、阻塞I/O
在进程空间调用recvfrom,其调用直到数据准备好并从内核拷贝到应用进程缓冲区时或者才生错误时,才返回。在此期间,会一直等待,进程从调用recvfrom开始到获取返回结果的整个时间段内都是被阻塞的,所以称为阻塞I/O。
2.2、非阻塞I/O
非阻塞IO通过进程反复调用IO函数(多次系统调用,并马上返回);在数据拷贝的过程中,进程是阻塞的。recvfrom从应用进程到内核的时候,如果该缓冲区没有数据,就直接返回一个EWOULDBLOCK错误,一般都对非阻塞I/O模型进行轮询检查这个状态,看内核是不是有数据到来。
2.3、I/O复用(select 和 poll)
Linux提供select/poll,进程通过将一个或者多个fd(文件描述符)传递给select或者poll系统调用,阻塞在select操作上。
这样select/poll可以检查多个fd是否处于就绪状态。select/poll是顺序扫描fd是否就绪,而且支持的fd数量有限,因此它的使用受到了一些限制。Linux还提供了了一个epoll系统调用,epoll使用基于事件驱动方式代替顺序扫描,因此性能更高。当有fd就绪时,立即回调函数rollback。
2.4、信号驱动I/O
首先我们允许套接口进行信号驱动I/O,并安装一个信号处理函数,进程继续运行并不阻塞。当数据准备好时,进程会收到一个SIGIO信号,可以在信号处理函数中调用I/O操作函数处理数据。
2.5、异步I/O
当一个异步过程调用发出后,调用者不能立刻得到结果。实际处理这个调用的部件在完成后,通过状态、通知和回调来通知调用者的输入输出操作。
3、I/O模型比较
阻塞I/O | 非阻塞I/O | I/O复用 | 信号驱动I/O | 异步I/O | |
---|---|---|---|---|---|
第一阶段:数据准备阶段 | 阻塞 | 轮询检查 | select就绪检查 | 异步 | 异步 |
第二阶段:数据拷贝阶段 | 阻塞 | 阻塞 | 阻塞 | 阻塞 | 异步 |
小结:
- 前四种I/O模型第一阶段处理不同,第二阶段处理相同(阻塞于recvfrom调用)
- 异步I/O处理两个阶段
- 信号驱动I/O模型与异步I/O模型区别在于:信号驱动I/O由内核通知我们何时可以开始下一个I/O操作;异步I/O模型由内核通知我们I/O操作何时完成