I/O多路复用这个概念被提出来以后, select是第一个实现 (1983 左右在BSD里面实现)。其函数原型如下:
该函数第一个参数表明我们要监听的文件描述符的最大值,中间的三个参数?readfds writefds exceptfds指向描述符集最后一个参数是超时时间。
它所需要的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就绪了,如果有则直接返回,如果没有,则进入休眠状态,直到被上述的回调函数唤醒或者超时时间到达。