IO总结 - 同步 异步 阻塞 非阻塞
开发过程中总避免不了IO,但是IO有那么多种,同步、异步、阻塞、非阻塞等等,到底区别在哪呢?
本篇讨论的IO特指Linux系统中的Network IO。
常见IO模型:
- blocking IO
- non-blocking IO
- IO multiplexing
- Asynchronous I/O
一个Network IO(以read操作为例)操作,涉及2系统对象。一个是调用这个IO的进程(Process)或线程(Thread),另一个是系统内核(Kernel),期间经历2个重要的阶段:
- 等待数据准备 (Waiting for the data to be ready)
- 将数据从内核拷贝到进程中 (Copying the data from the kernel to the process)
记住这两点很重要,因为IO Model的区别就是在两个阶段上各有不同的情况。
IO模型对比
IO模型 | 等待数据阶段 | Copy数据阶段 | 备注 |
---|---|---|---|
blocking IO | 阻塞 | 阻塞 | |
non-blocking IO | 非阻塞(轮询) | 阻塞 | |
IO multiplexing | 阻塞(Select) | 阻塞 | 相比blocking IO的优势在于可以同时处理多个连接 |
Asynchronous I/O | 非阻塞 | 非阻塞 | kernel负责将数据Copy到用户内存,然后通知用户进程 |
blocking IO 与 non-blocking IO 的区别
调用blocking IO会一直block住对应的进程直到操作完成,而non-blocking IO在kernel还准备数据的情况下会立刻返回。
synchronous IO 与 asynchronous IO 的区别
首先看一下POSIX对两者的定义 :
A synchronous I/O operation causes the requesting process to be blocked until that I/O operationcompletes;
An asynchronous I/O operation does not cause the requesting process to be blocked;
两者的区别就在于synchronous IO在做”IO operation”的时候会将process阻塞。
按照这个定义,之前所述的blocking IO,non-blocking IO,IO multiplexing都属于synchronous IO。
有人可能会说,non-blocking IO并没有被block啊?这里有个非常“狡猾”的地方,定义中所指的”IO operation”是指真实的IO操作,即Copy数据阶段。
asynchronous IO则不一样,当进程发起IO 操作之后,就直接返回再也不理睬了,直到kernel发送一个信号,告诉进程说IO完成。在这整个过程中,进程完全没有被block。
总结
经过上面的介绍,会发现non-blocking IO和asynchronous IO的区别还是很明显的。
在non-blocking IO中,虽然进程大部分时间都不会被block,但是它仍然要求进程去主动的check,并且当数据准备完成以后,也需要进程主动的再次调用recvfrom来将数据拷贝到用户内存。
而asynchronous IO则完全不同。它就像是用户进程将整个IO操作交给了他人(Kernel)完成,然后他人做完后发信号通知。在此期间,用户进程不需要去检查IO操作的状态,也不需要主动的去拷贝数据。
最后,再举几个不是很恰当的例子来说明这四个IO Model:
有A,B,C,D四个人在钓鱼:
A用的是最老式的鱼竿,所以呢,得一直守着,等到鱼上钩了再拉杆;
B的鱼竿有个功能,能够显示是否有鱼上钩,所以呢,B就和旁边的MM聊天,隔会再看看有没有鱼上钩,有的话就迅速拉杆;
C用的鱼竿和B差不多,但他想了一个好办法,就是同时放好几根鱼竿,然后守在旁边,一旦有显示说鱼上钩了,它就将对应的鱼竿拉起来;
D是个有钱人,干脆雇了一个人帮他钓鱼,一旦那个人把鱼钓上来了,就给D发个短信。
本篇参考:https://blog.csdn.net/historyasamirror/article/details/5778378