I/O 模型
I/O 模型
Unix 网络编程 (https://item.jd.com/11728741.html)
Unix 网络编程 (https://item.jd.com/11728741.html)
Unix 网络编程 (https://item.jd.com/11728741.html)
I/O 模型分类
Unix下可用的5种 I/O 模型:
- 阻塞式I/O;
- 非阻塞式I/O;
- I/O复用(select和poll);
- 信号驱动式I/O(SIGIO);
- 异步I/O(POSIX的aio_系列函数)
阻塞式 I/O 模型
用户进程调用recvfrom,其系统调用直到数据报到达且被复制到应用进程的缓冲区中或者发生错误才返回。最常见的错误是系统调用被信号中断,进程从调用recvfrom开始到它返回的整段时间内是被阻塞的。recvfrom成功返回后,应用进程开始处理数据报。
非阻塞式 I/O 模型
进程把一个套接字设置成非阻塞是在通知内核:当所请求的I/O操作非得把本进程投入睡眠才能完成时,不要把本进程投入睡眠,而是返回一个错误。
前三次调用recvfrom时没有数据可返回,因此内核转而立即返回一个EWOULDBLOCK错误。第四次调用recvfrom时已有一个数据报准备好,它被复制到应用进程缓冲区,于是recvfrom 成功返回。我们接着处理数据。
当一个应用进程像这样对一个非阻塞描述符循环调用recvfrom时,我们称之为轮询 (polling)。应用进程持续轮询内核,以查看某个操作是否就绪。这么做往往耗费大量CPU时间,不过这种模型偶尔也会遇到,通常是在专门提供某一种功能的系统中才有。
I/O 复用模型
有了I/O复用(I/O multiplexing),我们就可以调用select或poll,阻塞在这两个系统调用中的某一个之上,而不是阻塞在真正的I/O系统调用上。
我们阻塞于select调用阻塞于select调用,等待数据报套接字变为可读。当select返回套接字可读这一条件时,我们调用recvfrom把所读数据报复制到应用进程缓冲区。与阻塞式 I/O 模型相比,I/O复用并不显得有什么优势,事实上由于使用select需要两个而不是单个系统调用,I/O复用还稍有劣势。实际上,使用select的优势在于我们可以等待多个描述符就绪。
信号驱动式 I/O 模型
我们也可以用信号,让内核在描述符就绪时发送SIGIO信号通知我们。我们称这种模型为信号驱动式I/O(signal-driven I/O)
我们首先开启套接字的信号驱动式I/O功能,并通过sigaction系统调用安装一个信号处理函数。该系统调用将立即返回,我们的进程继续工作,也就是说它没有被阻塞。当数据报准备好读取时,内核就为该进程产生一个SIGIO信号。我们 随后既可以在信号处理函数中调用recvfrom读取数据报,并通知主循环数据已准备好待处理,也可以立即通知主循环,让它读取数据报。无论如何处理SIGIO信号,这种模型的优势在于等待数据报到达期间进程不被阻塞。主循环可以继续执行,只要等待来自信号处理函数的通知:既可以是数据已准备好被处理,也可以是数据报已准备好被读取。
异步 I/O 模型
告知内核启 动某个操作,并让内核在整个操作(包括将数据从内核复制到我们自己的缓冲区)完成后通知我们。这种模型与前一节介绍的信号驱动模型的主要区别在于:信号驱动式I/O是由内核通知我们何时可以启动一个I/O操作,而异步I/O模型是由内核通知我们I/O操作何时完成。
Unix 网络编程 (https://item.jd.com/11728741.html)
Unix 网络编程 (https://item.jd.com/11728741.html)
Unix 网络编程 (https://item.jd.com/11728741.html)
区别与联系
阻塞式 I/O 模型:
我可以采用 多线程+ 阻塞 IO 达到类似 I/O 复用模型效果,但是由于在多线程 + 阻塞 IO 中,每个socket对应一个线程,这样会造成很大的资源占用,并且尤其是对于长连接来说,线程的资源一直不会释放,如果后面陆续有很多连接的话,就会造成性能上的瓶颈。
I/O 复用模型:
通过一个线程就可以管理多个socket,只有当socket真正有读写事件发生才会占用资源来进行实际的读写操作。因此,多路复用IO比较适合连接数比较多的情况。
非阻塞式 I/O 模型:
非阻塞式 I/O 模型不断地询问socket状态是通过用户线程去进行的,而在I/O 复用模型,轮询每个socket状态是内核在进行的,这个效率要比用户线程要高的多。
注意点:
I/O 复用模型是通过轮询的方式来检测是否有事件到达,并且对到达的事件逐一进行响应。因此对于I/O 复用模型型来说,一旦某个事件响应时间长,那么就会导致后续的事件迟迟得不到处理,并且会影响新的事件轮询。