一、Unix可用的5种IO模型和区别:
1.阻塞式IO
2.非阻塞式IO
3.IO复用(select和poll)
4.信号驱动式IO(SIGIO)
5.异步IO(POSIX的aio_系列函数)
二、1.阻塞式IO模型:
最流行的IO模型是阻塞式IO模型
应用进程 内核
(recvfrom)------>系统调用---------> 无数据报准备好
|
等待数据
|
数据报准备好
|
将数据从内核复制到用户空间
|
处理数据报<-----返回成功指示<----- 复制完成
进程调用recvform,其系统调用直到数据报到达且被复制到应用进程的缓冲区中或者发生错误才返回。最常见的错误是系统调用被信号中断,我们说进程在从调用recvform开始到它返回的整段时间内是被阻塞的。recvfrom成功返回后,应用进程开始处理数据报。
2.非阻塞式IO模型
应用进程 内核
recvfrom----->系统调用---------> 无数据准备好
<---EWOULDBLOCK----
recvfrom----->系统调用---------> 无数据准备好
<---EWOULDBLOCK----
... ...
recvfrom------->系统调用-------> 数据准备好
复制数据报
|
处理数据报<------返回成功指示------完成复制
进程把一个套接字设置成非阻塞:当所有请求的IO操作非得把本进程投入睡眠才能完成时,不要把本进程投入睡眠,而是返回一个错误。
当一个一个应用程序对一个非阻塞描述符循环调用recvfrom时,我们称之为轮训polling。应用程序持续轮训内核,以查看某个操作是否就绪。
这么做往往消耗大量CPU时间。
3、IO复用模型
有了IO复用,我们就可以调用select或poll,阻塞在这2个系统调用中的某一个之上,而不是阻塞在真正的IO系统调用上。
应用进程 内核
select ------系统调用-----------> 无数据准备好
|
等待数据
|
<-----返回可读条件----- 数据准备好
recvfrom ----->系统调用------------> 复制数据报
|
将用户从内核复制到用户控件
|
处理数据报<----------返回成功指示-----复制完成
我们阻塞于select调用,等待数据报套接字变为可读。当selsect返回套接字可读这一条件时,我们调用recvfrom把所读数据报复制到应用进程缓冲区。
和上面模型比较IO复用并不显得有什么优势,事实上由于使用select需要两个而不是单个系统调用,IO复用还稍有劣势。
不过使用select的优势在于我们可以等待多个描述符就绪。