09.网络IO技术-阻塞、非阻塞、同步、异步
简介
- 同步调用、异步调用的说法,是对于获取数据的过程而言的。
- 例如发生read调用时,内核将数据从内核空间拷贝到应用程序空间。这个过程是在read函数中是
同步进行
的。如果内核实现的拷贝效率很差,read调用就会在这个同步过程中消耗比较长的时间。
- IO操作分两个阶段:
- 等待数据准备好 –读到内核缓存
- 将数据从内核读到用户空间 –读到进程空间
- 一般来说过程1花费的时间远远大于过程2:
BIO
:1上阻塞2上也阻塞的是同步阻塞IONIO
:1上非阻塞2阻塞的是同步非阻塞IO,Reactor就是这种模型AIO
:1上非阻塞2上非阻塞是异步非阻塞IO,Proactor模型就是这种模型
1. 阻塞I/O BIO
阻塞I/O发起的read请求,
线程会被挂起,一直等到内核数据准备好,并把数据从内核区域拷贝到应用程序的缓冲区中当拷贝过程完成,read 请求调用才返回
。之后应用程序可以对缓冲区的数据进行数据解析。
2. 非阻塞I/O NIO
非阻塞I/O的read请求
在数据未准备好的情况下立即返回
。应用程序可以不断轮询内核,直到数据准备好,内核将数据拷贝到应用程序缓冲,并完成这次read调用
。注意,
这里最后一次 read 调用获取数据的过程,是一个同步的过程
。这里的同步指的是内核区域的数据拷贝到缓存区这个过程
3. 非阻塞I/O多路复用 NIO
- 每次让应用程序去轮询内核的 I/O 是否准备好,是一个不经济的做法,因为在轮询的过程中应用进程啥也不能干
- select、poll、epoll 这样的 I/O 多路复用技术就隆重登场了。
- 通过
I/O事件分发
,当内核数据准备好时,再通知应用程序进行操作
。这个做法大大改善了应用进程对 CPU 的利用率,在没有被通知的情况下,应用进程可以使用 CPU 做其他的事情。

4. 异步I/O AIO
当我们
发起 aio_read 之后就立即返回
,内核自动将数据从内核空间拷贝到应用程序空间
。这个拷贝过程是异步的,内核自动完成的,和前面的同步操作不一样,应用程序并不需要主动发起拷贝动作。
5. 举例:
第一种阻塞 I/O 就是你去了书店,告诉老板你想要某本书,然后你就一直在那里等着,直到书店老板翻箱倒柜找到你想要的书。
第二种非阻塞 I/O 类似于你去了书店,问老板有没有一本书,老板告诉你没有,你就离开了。一周以后,你又来这个书店,再问这个老板,老板一查,有了,于是你买了这本书。
第三种基于非阻塞的 I/O 多路复用,你来到书店告诉老板:“老板,到货给我打电话吧,我再来付钱取书。”
第四种异步 I/O 就是你连去书店取书的过程也想省了,你留下地址,付了书费,让老板到货时寄给你,你直接在家里拿到就可以看了。
6. 总结:
- 和同步 I/O 相比,异步 I/O 的读写动作由内核自动完成。不过,在 Linux
下目前仅仅支持简单的基于本地文件的 aio
异步操作,这也使得我们在编写高性能网络程序时,首选
Reactor 模式
,借助 epoll 这样的 I/O 分发技术完成开发; - 而 Windows 下的
IOCP
则是一种异步 I/O 的技术,并由此产生了和 Reactor 齐名的Proactor 模式
。 - 无论是 Reactor 模式,还是 Proactor 模式,都是一种基于事件分发的网络编程模式。
- Reactor 模式是基于待完成的 I/O 事件,而 Proactor 模式则是基于已完成的 I/O 事件,两者的本质,都是借由事件分发的思想,设计出可兼容、可扩展、接口友好的一套程序框架。
7. Reactor与Proactor模型:
1、假如我们去饭店点餐,饭店人很多,如果我们付了钱后站在收银台
等着饭端上来我们才离开
,这就成了同步阻塞了。
2、如果我们付了钱后给你一个号就可以离开,
饭好了老板会叫号,你过来取
。这就是Reactor模型。
3、如果我们付了钱后给我一个号就可以坐到坐位上该干啥干啥,
饭好了老板会把饭端上来
送给你。这就是Proactor模型了。
本文作者:navyum
本文链接:https://www.cnblogs.com/navyum/p/18509334
版权声明:本作品采用知识共享署名-非商业性使用-禁止演绎 2.5 中国大陆许可协议进行许可。
【推荐】国内首个AI IDE,深度理解中文开发场景,立即下载体验Trae
【推荐】编程新体验,更懂你的AI,立即体验豆包MarsCode编程助手
【推荐】抖音旗下AI助手豆包,你的智能百科全书,全免费不限次数
【推荐】轻量又高性能的 SSH 工具 IShell:AI 加持,快人一步