poll/epoll用法简述

版权声明:本文为博主原创文章,未经博主允许不得转载。 https://blog.csdn.net/zhougb3/article/details/79797592
struct pollfd {  
 int fd;        //文件描述符  
 short events;  //要求查询的事件掩码  
 short revents; //返回的事件掩码  
};  
int poll(struct pollfd *ufds, unsigned int nfds, int timeout);  

struct pollfd * fds:是一个struct pollfd结构类型的数组,用于存放需要检测其状态的socket描述符;每当调用这个函数之后,系统不需要清空这个数组,操作起来比较方便;特别是对于 socket连接比较多的情况下,在一定程度上可以提高处理的效率;

poll是一个系统调用,其内核入口函数为sys_poll,sys_poll几乎不做任何处理直接调用do_sys_poll,do_sys_poll的执行过程可以分为三个部分:
1),将用户传入的pollfd数组拷贝到内核空间,因此拷贝操作和数组长度相关,时间上这是一个O(n)操作,这一步的代码在do_sys_poll中包括从函数开始到调用do_poll前的部分。
2),查询每个文件描述符对应设备的状态,如果该设备尚未就绪,则在该设备的等待队列中加入一项并继续查询下一设备的状态。查询完所有设备后如果没有一个设备就绪,这时则需要挂起当前进程等待,直到设备就绪或者超时,挂起操作是通过调用schedule_timeout执行的。设备就绪后进程被通知继续运行,这时再次遍历所有设备,以查找就绪设备。这一步因为两次遍历所有设备,时间复杂度也是O(n),这里面不包括等待时间。相关代码在do_poll函数中。
3),将获得的数据传送到用户空间并执行释放内存和剥离等待队列等善后工作,向用户空间拷贝数据与剥离等待队列等操作的的时间复杂度同样是O(n),具体代码包括do_sys_poll函数中调用do_poll后到结束的部分。

poll本质上和select没有区别,它将用户传入的数组拷贝到内核空间,然后查询每个fd对应的设备状态,如果设备就绪则在设备等待队列中加入一项并继续遍历,如果遍历完所有fd后没有发现就绪设备,则挂起当前进程,直到设备就绪或者主动超时,被唤醒后它又要再次遍历fd。这个过程经历了多次无谓的遍历。

它没有最大连接数的限制,原因是它是基于链表来存储的,但是同样有一个缺点:

1、大量的fd的数组被整体复制于用户态和内核地址空间之间,而不管这样的复制是不是有意义。
2、poll还有一个特点是“水平触发”,如果报告了fd后,没有被处理,那么下次poll时会再次报告该fd。

LINUX系统I/O复用技术之二:poll()

Linux socket之四:使用POLL机制处理多连接

Linux IO模式及 select、poll、epoll详解


epoll简述:

先简单看一下这篇

重点理解这篇

可参考

最好是先了解过select的原理再看。

epoll 水平触发与边缘触发

猜你喜欢

转载自blog.csdn.net/zhougb3/article/details/79797592