今天花了三个小时,带你彻底理解 IO多路复用中,epoll模式中通知的触发方式以及线程的阻塞和非阻塞选择

我们进一步理解LT 触发机制,需要明确 LT 模式的触发情况:

  • 只要内核 buffer 里有数据,epoll_wait 就会通知这个 FD 可读

进一步理解阻塞和非阻塞,需要从系统调用行为去看:

  • 用户进程调用 raed 后,如果没有数据可读,内核会让用户进程挂起,一直等到条件满足(有数据)才返回
  • 用户进程调用 read 后,如果没有数据,立刻返回 -1,并设置 errno=EAGAIN/EWOULDBLOCK,不会等待数据到来

在下面的场景中,用户 buffer 只有 1kb 空间,内核 buffer 中有 2kb。如果采用的是 LT + 非阻塞,那么用户读取了 1kb 之后,因为 LT 的机制(buffer 没读取完就会再次触发epoll_wait)会再次调用epoll_wait让用户去读取数据(再次调用的根本原因是 LT 触发机制)

在下面的场景中,用户 buffer 有 2kb 空间,内核 buffer 中有 1kb。如果采用的是 LT + 阻塞,那么用户读取了 1kb 之后,继续等待数据,用户进程因为没读取到要求的数据量会进入阻塞等待状态(这个等待就是正常等待新数据,没有达到 read 的返回条件,连接未断开且读缓存未满)。下次有新数据来的时候,会因为 LT 触发机制,会再次调用epoll_wait读取数据


在下面的场景中,用户 buffer 有 2kb 的空间,内核 buffer 中有 1kb 的空间。如果采用的是ET + 非阻塞,并且此时调用的 read 函数中,想要读取的大小是 2kb。用户首先将内核 buffer 中 1kb 的数据读取完毕,其次会就直接结束返回,不会进行死等状态,即使没有读到想要的数据大小。当然这个 FD 所对应的 Socket 在后续的时间写入了最后的 1kb,ep_poll_callback会再次触发,然后在下一次调用epoll_wait时,用户想要的数据都会被读取到

用户 buffer 有 2kb 的空间,内核 buffer 中有 1kb 的空间。如果采用的是ET + 阻塞,并且此时调用的 read 函数中,想要读取的大小是 2kb。用户首先将内核 buffer 中 1kb 的数据读取完毕,其次会进入死等状态。因为用户没有读取到想要的数据量,所以选择阻塞等待。但问题就在于,ET 模式只会在有新的数据时才进行触发,如果没有新数据到达,那 read 就将一直死等,并且如果用户 buffer 再一次读取中没有把内核 buffer 中的数据全部读光,那么可能永远不会有新通知提醒用户线程“buffer 还有数据”

评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值