五种I/O模型

一、一个输入操作的两个阶段:

阶段1:等待数据准备好;

阶段2:将数据从内核空间复制到用户进程空间。

对于一个socket上的输入操作,阶段一通常就是等待数据从网络中到达(数据到达后会被复制到内核中的某个缓冲区),阶段二是把数据从内核缓冲区复制到用户进程缓冲区。

recvfrom为系统调用,可以将操作在用户进程空间运行切换到在内核空间运行。

用户空间与内核空间:

我们知道现在操作系统都是采用虚拟存储器,那么对32位操作系统而言,它的寻址空间(虚拟存储空间)为4G(2的32次方)。操心系统的核心是内核,独立于普通的应用程序,可以访问受保护的内存空间,也有访问底层硬件设备的所有权限。为了保证用户进程不能直接操作内核,保证内核的安全,操心系统将虚拟空间划分为两部分,一部分为内核空间,一部分为用户空间。针对linux操作系统而言,将最高的1G字节(从虚拟地址0xC0000000到0xFFFFFFFF),供内核使用,称为内核空间,而将较低的3G字节(从虚拟地址0x00000000到0xBFFFFFFF),供各个进程使用,称为用户空间。每个进程可以通过系统调用进入内核,因此,Linux内核由系统内的所有进程共享。

 

 

五种I/O模型_第1张图片

二、阻塞式I/O:

五种I/O模型_第2张图片

其调用过程是直到数据包到达且被复制到应用进程的缓冲区中或者发生错误才返回,即从调用recvfrom开始到返回的整段时间内是阻塞的,recvfrom成功返回后,应用进程才开始处理数据报

三、非阻塞式I/O:

进程把一个套接字设置成非阻塞是在通知内核:当所请求的I/O操作非得把本进程投入睡眠才能完成时,不要把本进程投入睡眠,而是返回一个错误

五种I/O模型_第3张图片

前三次调用recvfrom时没有数据可返回,因此内核转而立即返回一个EWOULDBLICK错误,第四次调用recvfrom时已有一个数据报准备好,它被复制到应用进程缓存区,于是recvfrom成功返回,应用进程接着处理数据

当一个应用进程像这样对一个非阻塞描述符循环调用recvfrom时,称为轮询,持续轮询查看某个操作是否就绪,会耗费大量的CPU时间

四、I/O复用(select和epoll):

通过select或epoll,可以把阻塞的点转移到两个系统调用中的某一个之上,而不是阻塞在真正的I/O系统调用上

五种I/O模型_第4张图片

阻塞于select调用,等待数据报套接字变为可读,当select返回套接字可读条件时,调用recvfrom把所读数据报复制到应用进程缓冲区

但是I/O复用相比于阻塞I/O并不显得有什么优势,因为select需要使用系统调度为2个而不是单个,不过其优势在于可以等待多个描述符就绪

五、信号式驱动I/O(SIGIO):

通过使用信号的方式,让内核在描述符就绪时发送SIGIO信号通知应用进程,这种为信号驱动式I/O

五种I/O模型_第5张图片

首先开启套接字的信号驱动式I/O功能,并通过sigaction系统调用安装一个信号处理函数,该系统调用将立即返回,应用进程继续工作,没被阻塞;当数据报准备好读取时,内核为应用进程产生一个SIGIO信号,应用进程即可以在信号处理函数中调用recvfrom读取数据报并通知主循环数据已准备好待处理,也可以立即通知主循环,让它读取数据报

六、异步I/O:

异步I/O的工作机制是,告知内核启动某个操作,并让内核在整个操作(包括将数据从内核缓冲区复制到应用进程缓冲区)完成后通知我们,这种模型与信号驱动式I/O的主要区别在于:信号驱动式I/O是由内核通知我们何时可以启动一个I/O操作,而异步I/O是由内涵通知我们I/O操作何时完成

五种I/O模型_第6张图片

调用aio_read函数,给内核传递描述符、缓冲区指针、缓冲区大小、文件偏移量,并告诉内核当整个操作完成时如何通知我们,该系统调用立即返回,而且在等待I/O完成期间,我们的进程不会被阻塞,该信号知道数据已经复制到应用进程缓冲区才产生,这点不同于信号驱动式I/O

七、各种I/O模型的比较:

阻塞式I/O、非阻塞式I/O、I/O复用(select和epoll)、信号驱动式I/O(SIGIO)这4种模型的主要区别在于第一阶段,因为第二阶段都是一样的:在数据从内核复制到应用进程的缓存区期间,进程阻塞于recvfrom调用;相反的,异步I/O在这2个阶段都要处理

同步I/O与异步I/O的对比:

同步I/O操作:导致请求进程阻塞,知道I/O操作完成

异步I/O操作:不导致请求进程阻塞

五种I/O模型_第7张图片

因此,阻塞式I/O、非阻塞式I/O、I/O复用(select和epoll)、信号驱动式I/O(SIGIO)这4种模型都是同步I/O模型,因为其中真正的I/O操作(recvfrom)将阻塞进程,只有异步I/O模型是完全处理“等待数据+将数据从内核空间复制到应用进程空间”这两个阶段的操作

图来自《netty权威指南》

你可能感兴趣的:(I/O模型,linux,I/O模型)