多路复用 IO 模型中的函数 | 计算机基础

多路复用 IO 模型中的函数介绍。

select

它仅仅知道了,有 IO 事件发生了,却并不知道是哪几个流(可能有一个,多个,甚至全部),所以只能无差别轮询所有流,找出能读出数据,或者写入数据的流,对他们进行操作。所以 select 具有O(n) 的无差别轮询复杂度,同时处理的流越多,无差别轮询时间就越长。

select 本质上是通过设置或者检查存放 fd 标志位的数据结构来进行下一步处理。这样所带来的缺点是:

  • 单个进程可监视的 fd 数量被限制,即能监听端口的大小有限。一般来说这个数目和系统内存关系很大,具体数目可以使用 cat /proc/sys/fs/file-max 察看。32 位机默认是 1024 个。64 位机默认是 2048.
  • 对socket进行扫描时是线性扫描,即采用轮询的方法,效率较低。当套接字比较多的时候,每次都要通过遍历 FD_SETSIZE 个socket 来完成调度,不管哪个 socket 是活跃的,都遍历一遍。这会浪费很多 CPU 时间。如果能给套接字注册某个回调函数,当他们活跃时,自动完成相关操作,那就避免了轮询,这正是 epoll 与 kqueue 做的。
  • 需要维护一个用来存放大量 fd 的数据结构,这样会使得用户空间和内核空间在传递该结构时复制开销大。
  • select 的触发方式是水平触发,应用程序如果没有还完成对一个已经就绪的文件描述符的 IO 操作,那么下次 select 调用还会将这个文件描述符通知进程。

poll

与 select 相比,poll 使用链表保存文件描述符,因此没有了监视文件数量的限制,但是其他三个缺点依然存在。

epoll

上面所说的 select 缺点在 epoll 上不复存在,epoll 使用一个文件描述符管理多个描述符,将用户关心的文件描述符的事件存放到内核的一个事件表中,这样在用户空间和内核空间的 copy 只需一次。epoll 是事件触发的,不是轮询查询的。没有最大的并发连接限制,内存拷贝,利用 mmap() 文件映射内存加速与内核空间的消息传递。

epoll 有 LT 和 ET 两种触发模式,LT 是默认的模式,ET 是“高速”模式。

  • LT(水平触发):只要这个文件描述符还有数据可读,每次 epoll_wait 都会返回它的事件,提醒用户程序去操作。
  • ET(边缘触发):在它检测到有 IO 事件时,通过 epoll_wait 调用会得到有事件通知的文件描述符,对于每一个被通知的文件描述符,如可读,则必须将该文件描述符一直读到空,让 errno 返回 EAGAIN 为止,否则下次的 epoll_wait 不会返回余下的数据,会丢掉事件。如果ET模式不是非阻塞的,那这个一直读或一直写势必会在最后一次阻塞。

多路复用 IO 模型中的函数 | 计算机基础

http://www.zh0ngtian.tech/posts/f89d5075.html

作者

zhongtian

发布于

2020-03-01

更新于

2023-12-16

许可协议

评论