首先先通过一些简单的案例了解以下几个概念:
洗衣机洗衣服
洗衣机洗衣服(无论阻塞式IO还是非阻塞式IO,都是同步IO模型)
- 同步阻塞:你把衣服丢到洗衣机洗,然后看着洗衣机洗完,洗好后再去晾衣服(你就干等,啥都不做,阻塞在那边)
- 同步非阻塞:你把衣服丢到洗衣机洗,然后会客厅做其他事情,定时去阳台看洗衣机是不是洗完了,洗好后再去晾衣服(等待期间你可以做其他事情)
- 异步非阻塞:你把衣服丢到洗衣机洗,然后会客厅做其他事情,洗衣机洗好后会自动去晾衣服,晾完成后放个音乐告诉你洗好衣服并晾好了
下面讲解几个网络模型
BIO:同步阻塞模型
进程得一直等待数据完成才能进行下一步工作。(等衣服洗完)
基础NIO:同步非阻塞模型
进程可以去干别的事情,但是得不断反复检查数据是否准备完全。(去看电视但是得反复检查衣服洗完没有)
I/O多路复用
跟上面的NIO差不多,但是多路复用不再是一对一的关系,而是可以利用一个线程检测多个线程情况,减少线程的开销。后续会再详细说明多路复用
信号驱动
首先要允许接口进行信号驱动I/O,然后安装一个信号处理函数,线程继续运行并不阻塞。当数据准备好时,线程会收到一个SIGIO信号,可以在信号处理函数中调用I/O操作函数处理数据,这个用得比较少,我也不是很了解
Ok,经过上面的上面的讲解已经对同步是否阻塞已经有了认识,下面再讲讲同异步,其实上面的模型在后续对数据处理时都是阻塞的,对应上面例子就是不管你是否盯着洗衣机,最后都得你自己确认。而最后由洗衣机提示,就是异步I/O模型了
异步I/O
当一个异步过程调用发出后,调用者不能立刻得到结果。实际处理这个调用的部件在完成后,通过状态、通知和回调来通知调用者的输入输出操作。
总结
- IO操作分为两步
发起IO请求,等待数据准备(Waiting for the data to be ready)
实际的IO操作,将数据从内核拷贝到进程中(Copying the data from the kernel to the process)
- 前四种IO模型都是同步IO操作,区别在于第一阶段,而他们的第二阶段是一样的:在数据从内核复制到应用缓冲区期间(用户空间),进程阻塞于recvfrom调用或者select()函数。 相反,异步I/O模型在这两个阶段都要处理。
- 阻塞IO和非阻塞IO的区别在于第一步,发起IO请求是否会被阻塞,如果阻塞直到完成那么就是传统的阻塞IO,如果不阻塞,那么就是非阻塞IO。同步IO和异步IO的区别就在于第二个步骤是否阻塞,如果实际的IO读写阻塞请求进程,那么就是同步IO,因此阻塞IO、非阻塞IO、IO复用、信号驱动IO都是同步IO,如果不阻塞,而是操作系统帮你做完IO操作再将结果返回给你,那么就是异步IO。
阻塞非阻塞说的是线程的状态
同步和异步说的是消息的通知机制
同步需要主动读写数据,异步是不需要主动读写数据
同步IO和异步IO是针对用户应用程序和内核的交互
补充
一些别人的看法
https://www.zhihu.com/question/19732473/answer/117012135
然后:
整理的也很详细