IO模型(unix网络编程第一卷)
unix有五种I/O模型,好像其他系统也差不多吧。
I/O模型主要是两个阶段:等待数据与把数据从内核空间复制到用户空间,然后根据这两个阶段的不同,分类出来下面几类I/O模型。
前四个是同步IO,最后一个是异步IO,其分类是因为在第二阶段的不同。前面四个都是进程自己从内核空间复制数据,所以叫做同步;最后一个是操作系统将数据复制到进程的用户空间,然后通知进程去处理的,所以叫异步。
- 阻塞I/O
- 非阻塞I/O
- I/O复用(select/poll)
- 信号驱动I/O
- 异步I/O
阻塞I/O
一旦开启,直接将本进程或者线程中断停止,等满足条件再把他们拉起来跑。比如开启开启一个socket监听连接,采用这种方式,没有连接时,监听的线程直接阻断。
厕所就一个茅坑,一个人占了,你去了一直在那等啥事也不干,并且不看人坑位人是否走了。这样你这个线程就相当于被阻塞那了,
下列数据报套接字例子很直观。
非阻塞I/O
俩字:轮询
非阻塞与上面阻塞I/O最大区别就是线程或者进程是否被阻断。
进程把一个套接字设置成非阻塞是在通知内核:当所请求的I/O操作非得把本进程投入睡眠才能完成时,不要把本进程投入睡眠,而是返回一个错误。
比如开启开启一个socket监听连接,采用这种方式,没有连接时,监听的线程不被阻断,而是占用CPU资源不断轮询。
厕所就一个茅坑,一个人占了,你去了一直在那等啥事也不干,但是你一直查看是否有人。这样你这个线程就相当于没有被阻塞,还在做事。
下列例子更形象。
I/O复用
关键即使复用俩字,相当于同时监听多路I/O事件,当某个达到条件即可。但是所有被阻断的话,那线程或者进程也是要被阻断的哦。
有了IO复用(IO multiplexing),我们就可以调用select或poll,阻塞在这两个系统调用中的某一个之上,而不是阻塞在真正的IO系统调用上。图6-3概括展示了IO复用模型。
厕所就多个茅坑,多个人占了,你去了一直在那等啥事也不干,一直监听着所有的位置。
注意
信号驱动IO
这个主要是使用信号来通知IO好了,让进程去调用系统调用去读取数据。
我们也可以用信号,让内核在描述符就绪时发送sIGIo信号通知我们。我们称这种模型为信号驱动式I/O (signal-driven v/O),图6-4是它的概要展示。
厕所就一个茅坑,一个人占了,你去了没坑,报备一下,等没人了用信号通知你,你去就行了
异步I/O
它的关键就是异步俩字,其与上面四种最大区别就是这个数据从内核空间复制到用户空间由内核完成。
这种模型与前一节介绍的信号驱动模型的主要区别在于:信号驱动式IO是由内核通知我们何时可以启动一个IO操作,而异步IO模型是由内核通知我们I/O操作何时完成。图6-5给出了一个例子。
厕所就一个茅坑,但这个是一个移动坑,一个人占了,你去了没坑,报备一下,等没人了直接移动到你旁边,不用你去,直接享受服务。
BIO、NIO、AIO
- BIO 同步阻塞
- NIO 同步非阻塞
- AIO 异步非阻塞
BIO 上面第一种
同步并阻塞,服务实现模式为一个连接对应一个线程,即客户端发送一个连接,服务端要有一个线程来处理。如果连接多了,线程数量不够,就只能等待,即会发生阻塞。
NIO 上面第三种
同步非阻塞,服务实现模式是一个线程可以处理多个连接,即客户端发送的连接都会注册到多路复用器上,然后进行轮询连接,有I/O请求就处理
AIO 上面第五种
同步非阻塞,服务实现模式是一个线程可以处理多个连接,即客户端发送的连接都会注册到多路复用器上,然后进行轮询连接,有I/O请求就处理