linux中的select和epoll模型
Linux中有三种常见的I/O多路复用技术select、poll和epoll.它们的的出现是为了解决程序在进行大量I/O操作(如网络通信)时的阻塞问题,使得用户程序在I/O可用时得到通知,而不必一直阻塞等待每一个I/O操作。
I/O多路复用这个概念被提出来以后, select是第一个实现 (1983 左右在BSD里面实现)。其函数原型如下:
该函数第一个参数表明我们要监听的文件描述符的最大值,中间的三个参数?readfds, writefds, exceptfds,指向描述符集,最后一个参数是超时时间。
select处理流程如图所示:
但是,select模型有着一个很大的问题,那就是它所支持的fd的数量是有限制的,从linux源码中所看
它所需要的fd_set类型其实是一个__FD_SETSIZE长度bit的数组。也就是说通过FD_SET宏来对它进行操作的时候,需要注意socket不能过大,否则可能出现数组写越界的错误。
而linux在2.6 内核中引入的epoll模型,就彻底解决了这个问题。
epoll模型提供了三个接口:
其使用流程基本与select一致,大致如下:
epoll_create函数会为要监听的fd分配内存。
epoll_ctl函数将要监听的fd拷贝到内核空间,从而避免每次等待事件都要进行内存拷贝。同时,注册一个回调函数到 fd的设备等待队列中,这样,当设备就绪的时候,驱动程序可以直接调用回调函数进行处理,从而避免了对所有监听fd的轮循。
epoll_wait函数会检查是否已经有fd就绪了,如果有则直接返回,如果没有,则进入休眠状态,直到被上述的回调函数唤醒或者超时时间到达。
关于select和epoll的源码深层次分析,可以参考以下文章
http://blog.csdn.net/lizhiguo0532/article/details/6568964
http://hongxiaolong.com/posts/epoll.html