IO 模型
0 I/O 模型
在I/O模型中,设想如此场景 : application
通过kernel
的read
函数读取数据,但是kernel
还未准备好数据。那么此时read
函数有两种处理方式(大致的流程):
1 | 等待数据准备好后再返回。此时: 对于 application 是Blocking 的。对于 kernel 的read 函数是Synchronous 的。 |
||
2 | 立即返回,告知application 数据还未准备好。此时:对于 application 是Non-Blocking 的;对于 kernel 的read 函数是Asynchronous 的。由于 read 函数没有返回application 期望读到的数据,那么就必须通过另外的方式把数据给到application 。那么此时,也有2种处理方式: |
||
2.1 |
application 一直不停的调用read 函数,直到返回了期望读到的数据。此时read 函数虽然没有Blocking 到application ,但是application 也无法处理其他事情,只能不停的调用read 。 |
||
2.2 |
read 函数要求application 调用时提供一个callback_function ,在数据准备好时通过callback_function 告知application 。此时application 就可以继续做其他事情,直到callback_function 被调用。在处理 callback_function 时,也还有2种处理方式。 |
||
2.2.1 | 数据准备好时调用callback_function ,交由application 去读取。 |
||
2.2.2 | 数据准备好并且写入到application 提供的缓冲区,调用callback_function 。 |
1 Blocking I/O
对应上述表格中的1。这种方式模型简单,Blocking
时application
的进程/线程被挂起,基本不会占用CPU
资源。但是当并发大时就需要创建N个进程/线程,造成内存、线程切换开销增大。
2 Non-Blocking I/O
对应上述表格中的2.1。这种方式明显看起来和Blocking
没什么区别,不停的调用会造成CPU负担过重。
3 I/O Multiplexing (select, poll, epoll)
对应上述表格中的2.1。但是会同时通过(select, poll, epoll)在一个进程/线程中Blocking
多个连接(故而称为I/O多路复用
),当其中有一个连接的有数据可读时就返回。但是实质上还是Blocking
的,只是不会Blocking
到read
环节,而是(select, poll, epoll)环节。因为不会为每个连接创建对应的进程/线程,故而性能较好。
4 Signal Driven I/O (SIGIO)
对应上述表格中的2.2.1。
5 Asynchronous I/O (POSIX aio, Windows iocp)
对应上述表格中的2.2.2。当application
接收到回调通知时,数据已经复制给application
,故而性能最佳。