有哪些常用的IO模型?

q1871901600 发布于 2024-11-16 14 次阅读


select

通过数组实现的运行队列,当绑定的任务数据没有到达进程时会让出CPU。

当网卡接收到数据,然后网卡通过中断信号通知 CPU 有数据到达,执行中断程序,中断程序主要做了两件事:

1)将网络数据写入到对应 socket 的数据接收队列里面;

2)唤醒队列中的等待进程 A,重新将进程 A 放入 CPU 的运行队列中;

1.性能开销大

1)调用 select 时会陷入内核,这时需要将参数中的 fd_set 从用户空间拷贝到内核空间,select 执行完后,还需要将 fd_set 从内核空间拷贝回用户空间,高并发场景下这样的拷贝会消耗极大资源;(epoll 优化为不拷贝)

2)进程被唤醒后,不知道哪些连接已就绪即收到了数据,需要遍历传递进来的所有 fd_set 的每一位,不管它们是否就绪;(epoll 优化为异步事件通知)

3)select 只返回就绪文件的个数,具体哪个文件可读还需要遍历;(epoll 优化为只返回就绪的文件描述符,无需做无效的遍历)

2.同时能够监听的文件描述符数量太少。受限于 sizeof(fd_set) 的大小,在编译内核时就确定了且无法更改。一般是 32 位操作系统是 1024,64 位是 2048。(poll、epoll 优化为适应链表方式)

第 2 个缺点被 poll 解决,第 1 个性能差的缺点被 epoll 解决。

poll

管理多个描述符也是进行轮询,根据描述符的状态进行处理,但 poll 无最大文件描述符数量的限制因其基于链表存储

select 和 poll 在内部机制方面并没有太大的差异。相比于 select 机制,poll 只是取消了最大监控文件描述符数限制,并没有从根本上解决 select 存在的问题。

epoll

基于红黑树的数据结构优化了poll的检索效率问题,同时通过就绪队列维护就绪事件,无需做无效的遍历

一个会写python的Java工程师
最后更新于 2024-11-16