阻塞IO、非阻塞IO、同步IO,异步IO

  再说一下IO发生时涉及的对象和步骤。对于一个network IO (这里我们以read举例),它会涉及到两个系统对象,一个是调用这个IO的process (or thread),另一个就是系统内核(kernel)。当一个read操作发生时,该操作会经历两个阶段:

#1)等待数据准备 (Waiting for the data to be ready)
#2)将数据从内核拷贝到进程中(Copying the data from the kernel to the process)

    记住这两点很重要,因为这些IO模型的区别就是在两个阶段上各有不同的情况。

    补充:

#1、输入操作:read、readv、recv、recvfrom、recvmsg共5个函数,如果会阻塞状态,则会经理wait data和copy data两个阶段,如果设置为非阻塞则在wait 不到data时抛出异常

#2、输出操作:write、writev、send、sendto、sendmsg共5个函数,在发送缓冲区满了会阻塞在原地,如果设置为非阻塞,则会抛出异常

#3、接收外来链接:accept,与输入操作类似

#4、发起外出链接:connect,与输出操作类似

二 阻塞IO(blocking IO)

阻塞IO、非阻塞IO、同步IO,异步IO

过程:

当用户调用了recvfrom这个系统调用时,kernal开始第一个阶段,准备数据,在数据还未准备好时不会反悔任何东西,用户会被阻塞在recvfrom,直到数据准备完毕并且从kernal中把数据拷贝到用户内存后才不阻塞,在此之前用户只能一直等待。

  几乎所有的程序员第一次接触到的网络编程都是从listen()、send()、recv() 等接口开始的,使用这些接口可以很方便的构建服务器/客户机的模型。然而大部分的socket接口都是阻塞型的。

    ps:所谓阻塞型接口是指系统调用(一般是IO接口)不返回调用结果并让当前线程一直阻塞,只有当该系统调用获得结果或者超时出错时才返回。

三 非阻塞IO(non-blocking IO)

阻塞IO、非阻塞IO、同步IO,异步IO

过程:

当用户调用了recvfrom这个系统调用时,kernal开始第一个阶段,准备数据,在数据还未准备好时,会返回一个error,不会阻塞用户进程,此时用户可以做其他事,每隔一段时间询问数据是否准备好,当收到数据准备好后,则进入copydata阶段,既把数据从kernal拷贝到用户内存中,但是这个拷贝的过程用户仍然是被阻塞的,如果遇到数据量大的情况,用户会被长时间阻塞。

所以,在非阻塞式IO中,用户进程其实是需要不断的主动询问kernel数据准备好了没有。

缺点:1、会循环调用recvfrom,大幅增大cpu的占用率

2、任务完成的响应延时增大,任务可能会夹在两个轮询之间,降低数据的吞吐量。

四 多路复用IO(IO multiplexing)

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

阻塞IO、非阻塞IO、同步IO,异步IO

   当用户进程调用了select,那么整个进程会被block,而同时,kernel会“监视”所有select负责的socket,当任何一个socket中的数据准备好了,select就会返回。这个时候用户进程再调用read操作,将数据从kernel拷贝到用户进程。
    这个图和blocking IO的图其实并没有太大的不同,事实上还更差一些。因为这里需要使用两个系统调用(select和recvfrom),而blocking IO只调用了一个系统调用(recvfrom)。但是,用select的优势在于它可以同时处理多个connection。

    强调:

    1. 如果处理的连接数不是很高的话,使用select/epoll的web server不一定比使用multi-threading + blocking IO的web server性能更好,可能延迟还更大。select/epoll的优势并不是对于单个连接能处理得更快,而是在于能处理更多的连接。

    2. 在多路复用模型中,对于每一个socket,一般都设置成为non-blocking,但是,如上图所示,整个用户的process其实是一直被block的。只不过process是被select这个函数block,而不是被socket IO给block。

    结论: select的优势在于可以处理多个连接,不适用于单个连接  

五 异步IO(Asynchronous I/O)

阻塞IO、非阻塞IO、同步IO,异步IO

当用户发起recvfrom指令后,直接做其他事,当数据准备好后,会自动把数据从kernal拷贝到用户内存,之后再发一个完成的信号,读取完成。