GoLang之说说IO多路复用[第二话]

在这里插入图片描述
在这里插入图片描述
在这里插入图片描述
在这里插入图片描述
在这里插入图片描述
在这里插入图片描述
在这里插入图片描述

在这里插入图片描述
在这里插入图片描述
在这里插入图片描述
在这里插入图片描述
在这里插入图片描述

操作系统会为每个TCP socket,
分配一个读缓冲区和一个写缓冲区。
对方返回的数据会先存入读缓冲区,
要发送的数据也要先拷贝到写缓冲区。
缓冲区在内核空间,
应用程序不能直接操作,
只能通过系统调用来进行。

现在的问题是,
用户程序想要读数据的时候,
读缓冲区里未必有数据!
想发送数据的时候,
写缓冲区里未必有空间!
那怎么办?

第一种办法:
乖乖的让出CPU,
进到等待队列里,
等socket可读或可写了,
再获得时间片就可以继续执行了,
这就是“阻塞式IO”。

第二种办法:
被称为“非阻塞式IO”,
就是不让出CPU,
但需要频繁的检查
socket是否可操作了。
这是一种“忙等待”的方式,
效率比较低。

第三种办法:
就是我们今天的主角,
“IO多路复用”了。
通过IO多路复用,
一个线程可以通过一次系统调用
同时监听多个socket,
不需要持续轮询而空耗CPU,
并发处理能力也因此大幅提升!

美中不足的是,
IO多路复用的事件循环
会和具体业务逻辑耦合,
把原本连续的业务逻辑,
打散为一个一个的事件处理,
就像一个“状态机”。
这并不更符合常规开发习惯,
不过,
若是与“协程”合作起来,
那就不一样了!