select/poll/epoll

I/O 复用

I/O多路复用就通过一种机制,可以监视多个描述符,一旦某个描述符就绪(一般是读就绪或者写就绪),能够通知程序进行相应的读写操作。但select,poll,epoll本质上都是同步I/O,因为他们都需要在读写事件就绪后自己负责进行读写,也就是说这个读写过程是阻塞的,而异步I/O则无需自己负责进行读写,异步I/O的实现会负责把数据从内核拷贝到用户空间。 
epoll的效率更高,优化了select的轮询操作,通过callback事件响应方式。 
epoll除了提供select/poll那种IO事件的水平触发(Level Triggered)外,还提供了边缘触发(Edge Triggered),这就使得用户空间程序有可能缓存IO状态,减少epoll_wait/epoll_pwait的调用,提高应用程序效率。


select :

其参数是输入输出型参数,每次调用都重新将添加关心的描述符集。
监视文件描述符有上限,默认只有1024。
每次调用都会在用户空间和内核空间之间拷贝 fd 集。
每次调用内核和开发者都要变量所有fd,复杂度 O(N),当数量很多时,开销比较大。
性能高于多线程或多进程版本。


poll :

poll 解决的 select 的文件描述符上限问题,上限是最大可以打开文件的数目,这个数字一般远大于2048,举个例子,在1GB内存的机器上大约是10万左右,具体数目可以cat /proc/sys/fs/file-max察看,一般来说这个数目和系统内存关系很大。
同 select一样, 不论文件描述符是否就绪,都会将大量文件描述符的数组被整体复制于用户态和内核的地址空间之间。
将关心事件与发生事件在 不同的 event中,避免了像 select一样每次都要重新赋值。
每次调用内核和开发者都要遍历所有fd,复杂度 O(N),当数量很多时,开销比较大。
可以说poll是加强版的 select,其使用模型也十分相似。


epoll:

上限和 poll 一样,不再受限于文件描述符的限制。
不必在内核和用户空间多次拷贝fd 集合,只需要在使用前添加到集合即可,在不关心时删除即可。
内核操作描述符从线性的 O(N)提高到 O(log2n),效率更高。
阻塞等待时,内核只需要检测就绪队列是否有事件就绪,当返回时候,如果有事件就绪,则用户可以根据返回值知道就绪事件的范围,不需像 另外两者,会变量所有描述符。
epoll 可以说是poll 的加强版,其缺陷是目前不支持跨平台只在 Linux支持,且当有大量活跃的描述符时效率不及另外两者。
 

猜你喜欢

转载自blog.csdn.net/fadbgfnbxb/article/details/88787082