IO模式
对于一次IO访问(以read举例),数据会先被拷贝到操作系统内核的缓冲区中,然后才会操作系统内核的缓冲区拷贝到应用程序的地址空间。所以说,当一个read操作发生时,它会经历两个阶段:
1. 等待数据准备(Walting for the data to be ready)
2. 将数据从内核拷贝到进程中(Copying the data from the kernel to the process)
正因为这两个阶段,Linux系统产生了下面五种网络模式的方案。
- 阻塞I/O (blocking IO)
- 非阻塞I/O (nonblocking IO)
- I/O 多路复用 (IO multiplexing) 主流都用这个
- 信号驱动 I/O (signal driven IO) 实际中并不常用
- 异步I/O (asynchronous IO)


IO multiplexing就是我们说的select ,poll,epoll,有些地方也称这种I/O方式为event driven IO(事件驱动IO) 。 select / epoll 的好处就在于单个process就可以同时处理多个网络连接的IO。 它的基本原理就是select , poll ,epoll,这个function会不断的轮询所负责的所有socket,当莫个socket有数据到达了,就通知用户进程。

当用户调用了select,那么整个进程会被block,而同时,kernel会‘监视’所有select负责socket,当任何一个socket中的数据准备好了,select就返回。这个时候用户进程再调用read操作,将数据从kernel拷贝到用户进程。
所以,I/O多路复用的特点是通过一种机制一个进程能同时等待多个文件描述符,而这些文件描述符(套接字描述符)其中的任意一个进入读取状态,select()函数就可以返回。
如果处理的连接数不是很高的话,使用select/epoll 的web server不一定比使用multi - threading + blocking IO的web server性能更好,可能延迟还更大。select/epoll 的优势并不是对于单个连接能处理得更快,而是在于能处理更多的连接。
在IO multiplexing Model中,实际上,对于每一个socket,一般都设置成non-blocking ,但是,如上图所示,整个用户的process其实是一直被block的。只不过process是被select这个函数block,而不是被socket IO给block。
Linux下的asynchronous IO其实用很少。

用户进程发起read操作之后,立刻就可以开始去做其他的事。而另一方面,从kernel的角度,当它受到一个asynchronous read之后, 首先它会立刻返回,所以不会对用户进程产生任何block。然后,kernel会等待数据准备完成,之后将数据拷贝到用户内存,当这一切都完成以后,kernel会给用户进程发送一个signal,告诉它read操作完成了。


浙公网安备 33010602011771号