IO-同步,异步,阻塞,非阻塞
IO-同步,异步,阻塞,非阻塞
1.什么是IO
数据在系统内核(kernel)和用户进程之间的传递,称为IO。
2.IO操作步骤
以read为例,涉及两个系统对象,调用IO的process(or thread),即用户进程;另一个为系统内核(kernel)。
当用户进程调用recvfrom操作时,会经历两个阶段
1)等待数据准备
2)将数据从内核拷贝至进程中
3.IO模型
根据用户进程在IO操作时的状态,可以分为5中IO类型:
blocking IO:阻塞IO
non-blocking IO:非阻塞IO
IO multiplexing:多Socket连接IO
signal driven IO:信号驱动IO
asynchronous IO:异步IO
signal driven IO实际中很少使用,在此不做介绍。
2.blocking IO:阻塞IO
当用户进程调用recvfrom时,首先开始IO第一阶段:kernel准备数据。
用户进程会被阻塞。当kernel数据准备好以后,会将数据从kernel拷贝到用户内存,然后kernel返回结果,用户进程才会解除block的状态,重新运行起来。
blocking IO在IO执行的两个阶段都被block了。
3.non-blocking IO:非阻塞IO
可以设置socket使其变为non-blocking。
当对一个non-blocking socket执行recvfrom操作时,流程如下:
用户进程调用recvfrom,如果kernel数据还没有准备好,此时用户进程不会被block。而是立刻返回一个error,从用户进程角度看,它并没有等待,而是立刻得到了一个结果。
用户进程判断是一个error时,它就知道数据还没有准备好,于是再次发送read操作。
一旦kernel中的数据准备好,并且再次收到了用户进程的system call,那么它马上将数据拷贝到用户内存,然后kernel返回结果。
non-blocking IO在数据准备阶段,没有被block,而是不断的轮询kernel数据是否准备好;在数据拷贝阶段,用户进程被block,直到kernel拷贝结束,返回结果,用户进程才会解除block的状态。
4.IO multiplexing:多Socket连接IO
IO multiplexing的特点是单个用户进程可以同时处理多个网络连接IO,它的原理是select/epoll这个function会不断的轮询所负责的所有socket,当某个socket有数据到达了,就通知用户进程。
当用户进程调用select时,整个进程会被block,当任何一个socket中的数据准备好了,select就会返回。这时用户进程再调用read操作,将数据从kernel拷贝到用户进程。我们可以看出,IO multiplexing和blocking IO的流程类似,不同的是,IO multiplexing需要两个system call(select和recvfrom),而blocking IO只调用了一个system call(recvfrom)。select的优势在于它可以同时处理多个socket连接。所以如果连接数不高的话,使用select/epoll的web server不一定比multi-threading+blocking IO的web server性能更好,select/epoll的优势在于能够处理更多的连接。
IO multiplexing中,每一个socket一般设置为non-blocking的,但是用户进程一直是被select函数block的。
5.asynchronous IO
用户进程发起read操作后,立刻返回可以去做其他的事情了。
此时,从kernel角度看,当它收到一个asynchronous read后,首先他立刻返回,所以不会对用户进程产生任何block,然后,kernel等待数据准备完成,然后将数据拷贝到用户内存,当这一切完成之后,kernel会给用户进程发送一个signal告诉用户进程read操作完成了。
6.四种IO模型的区别
blocking和non-blocking,synchronous IO和asynchronous IO的区别。
blocking和non-blocking的区别很明显,blocking会一致阻塞,non-blocking在数据没准备完全时会立刻返回。
synchronous同步IO指的是在IO操作时会阻塞用户进程;asynchronous含义相反。
可以看出blocking,non-blocking,IO multiplexing都是synchronous IO;而asynchronous不会对用户进程产生任何阻塞。
7.网上有一个比较形象的例子来说明这四种IO Model
有A,B,C,D四个人在钓鱼:
A用的是最老式的鱼竿,所以呢,得一直守着,等到鱼上钩了再拉杆;
B的鱼竿有个功能,能够显示是否有鱼上钩,所以呢,B就和旁边的MM聊天,隔会再看看有没有鱼上钩,有的话就迅速拉杆;
C用的鱼竿和B差不多,但他想了一个好办法,就是同时放好几根鱼竿,然后守在旁边,一旦有显示说鱼上钩了,它就将对应的鱼竿拉起来;
D是个有钱人,干脆雇了一个人帮他钓鱼,一旦那个人把鱼钓上来了,就给D发个短信。