IO操作包含两步:
1.请求结果 2.返回结果,其中所需时间不确定
阻塞:请求结果后线程挂起(不执行其他操作)
非阻塞:请求结果后立即返回(可执行自定义的其他操作)
阻塞与非阻塞区别
同步:返回结果过程(内核复制数据到用户空间)阻塞
异步:返回过程不阻塞,利用回调机制唤醒
同步与异步区别
IO多路复用
select:将遍历fd数组的操作交给内核执行,减少上下文切换的开销,返回标记过的数组。
select
poll:和 select 的主要区别是去掉了 select 只能监听 1024 个文件描述符的限制。
select问题及其改进epoll
- select 调用需要传入 fd 数组,需要拷贝一份到内核,高并发场景下这样的拷贝消耗的资源是惊人的。(可优化为不复制)
- select 在内核层仍然是通过遍历的方式检查文件描述符的就绪状态,是个同步过程,只不过无系统调用切换上下文的开销。(内核层可优化为异步事件通知)
- select 仅仅返回可读文件描述符的个数,具体哪个可读还是要用户自己遍历。(可优化为只返回给用户就绪的文件描述符,无需用户做无效的遍历)
所以 epoll 主要就是针对这三点进行了改进。
- 内核中保存一份文件描述符集合,无需用户每次都重新传入,只需告诉内核修改的部分即可。
- 内核不再通过轮询的方式找到就绪的文件描述符,而是通过异步 IO 事件唤醒。
- 内核仅会将有 IO 事件的文件描述符返回给用户,用户也无需遍历整个文件描述符集合。
epoll