分类: LINUX
2013-03-08 09:58:09
poll和select在面对高并发多连接的场景时,仍然有瓶颈,除了上述的关于每次调用都需要做一次从用户空间到内核空间的拷贝,还有这样的问题,poll和select会不得不多次操作,并且每次操作都很有可能需要多次进入睡眠状态,也就是多次全部轮询fd,出现重复而无意义的操作。
重复而无意义的操作包括:
首先 从用户到内核空间拷贝,既然长期监视这几个fd,甚至连期待的事件也不会改变,那拷贝无疑就是重复而无意义的,
可以让内核长期保存所 有需要监视的fd甚至期待事件,或者可以再需要时对部分期待事件进行修改;
其次 将当前线程轮流加入到每个fd对应设备的等待队列,这样做无非是哪一个设备就绪时能够通知进程退出调用,
可以找个“代理”的回调函数,代替当前进程加入fd的等待队列好了(Linux的等待队列,实质上是回调函数队列,
也可以使用宏来将当前进程“加入”等待队列,其实就是将唤醒当前进程的回调函数加入队列)。
poll改进后,就是epoll
像poll系统调用一样,做轮询文件操作发现尚未就绪时,它就调用传入的一个回调函数,这是epoll指定的回调函数,
它不再像以前的poll系统调用时指定的回调函数那样,而是就将那个“代理”的回调函数加入设备的等待队列,
这个代理的回调函数就等待设备就绪时将它唤醒,然后它就把这个设备fd放到一个指定的地方,
同时唤醒可能在等待的进程,到这个指定的地方取fd。