一个数入操作通常包括两个不同的阶段:
(1)等待数据准备。
(2)从内核项进程复制数据。
对于一个套结字上的输入操作,第一步通常涉及等待数据从网络中到达。当所等待的数据从网络中到达。当所等待分组到达时,它被复制到内核中的某个缓冲区。第二步就是把数据从内核缓冲区复制到应用进程缓冲区。
一. I/O模型
1.阻塞性I/O模型
进程调用recvfrom,其系统调用直到数据报到达且被复制到应用进程的缓冲区中或者发生错误才返回。recvfrom成功返回后,应用进程开始处理数据包。
2.非阻塞式I/O模型
进程把一个套结字设置为非阻塞是为了通知内核:当所请求的 I/O操作非得把本进程投入睡眠才能完成时,不要把进程投入睡眠,而是返回一个错误(即若无数据则不等待),当一个应用进程像这样对一个非阻塞描述符循环调用recvfrom时,我们称之为轮询。然而这么作往往会消耗大量的CPU时间,所以通常是在专门提供一种功能的系统时采用。
3.I/O复用模型
有了I/O复用,我们就可以调用select和poll,阻塞在 这两个系统调用中的某一个上,而不是阻塞在真正的I/O系统调用上。
我们阻塞于select调用,等待数据报套结字变为可读。当select返回套结字可读这一条件时我们调用recvfrom把所读数据报复制到应用进程缓冲区。
而事实上select需要两个而不是单个系统调用,所以在这方面I/O复用还稍有劣势,但是select的优势在于其可以等待多个描述符就绪。
4.信号驱动式I/O
使用信号让内核在描述符就绪是发送SIGIO信号通知我们的方式为信号驱动式I/O。
我们首先开启套结字的信号驱动式I/O功能,并通过sigaction系统调用安装一个信号处理函数。让系统调用立即返回,我们的进程继续工作,也就是可以说没有被阻塞。当数据报准备好读取时,内核则产生一个SIGIO信号。我们随后即可在信号处理函数中调用recvfrom读取数据报,并通知主循环数据以准备好待处理,也可以立即停止主循环,让他读取数据报。
这种模型的优势在于等待数据报到达期间进程不被阻塞。主循环可以继续执行,只要等待来自信号处理函数的通知。
5.异步I/O模型
异步I/O操作昊苏内核某个操作,并让内核在整个操作完成后通知我们。这种模型于信号驱动模型类似,但不同的是,信号驱动模型告诉我们何时可以启动I/O操作,而异步I/O模型是由内核通知我们I/O操作何时完成。
二. 各种I/O模型的比较
同步I/O操作:导致请求进程阻塞,直到I/O操作完成。
异步I/O操作:不导致请求进程阻塞。