100%弄明白5种IO模型 - 知乎 (zhihu.com)
对此文章的理解:
本质: 一条消息 是如何 从一个人 发送到 另外一个人的;
由上图可知:
1.缓冲区 也是 池化 的一种思想,一次性 读/取 一批数据;
2.读/取 的数据 都是从 缓冲区里 拿的;
阻塞IO |非阻塞IO
思考一个问题:
应用之间 发送消息 是间断性的(发送的时间 是随意的),
场景1:
图中 缓冲区 还没有 接收到 该读取的消息时,
那此时 你向缓冲区 发起读取申请,
接收缓冲区 是应该马上告诉你说:
现在还没你的数据,让你在这里等着,直到有数据了 再把数据交给你。
把这个问题应用到第一个步骤也是一样,
你向 缓冲区 发送数据时,
如果 缓冲区满了,
那是 告诉你:
现在没空间了,让你等待着,等缓冲区有空间了 再把你的数据 拷贝到 缓冲区。
阻塞IO
如果上面的问题你已经思考过了,那么其实你已经明白了什么是阻塞IO了,
阻塞IO: 当你 发起 读取数据申请时,在 内核数据 没有准备好之前,
你会一直处于等待数据状态,直到内核把数据准备好了交给你才结束。
术语描述:在应用调用recvfrom读取数据时,其 系统调用 直到数据包到达 且 被复制到应用缓冲区中 或者 发送错误时才返回,在此期间一直会等待,进程从调用到返回这段时间内都是被阻塞的称为阻塞IO;
流程:
1、应用进程向内核发起recfrom读取数据。
2、准备数据报(应用进程阻塞)。
3、将数据从内核复制到应用空间。
4、复制完成后,返回成功提示。
延申:
TCP传数据(TCP/IP 协议、七层模型)
IO多路复用 epoll
总结:复用IO的基本思路就是 通过slect或poll、**epoll 来监控多fd** ,来达到 **不必为每个fd创建一个对应的监控线程**,从而**减少线程资源创建** 的目的。
总结: IO复用模型里面的 select虽然可以监控多个fd了,但select其实现的本质上是通过 不断的轮询fd来监控数据状态, 因为**大部分轮询请求其实都是无效的**,所以信号驱动IO意在通过这种建立信号关联的方式,实现了 发出请求后 **只需要等待数据就绪的通知即可**,这样就可以避免大量无效的数据状态轮询操作。