I/O多路复用技术可以避免当要处理多个文件描述符时,长时间阻塞在某个文件描述符,使其他描述符得不到处理的情况。多进程、非阻塞(轮询)、异步I/O技术都可用来处理该问题,I/O多路复用是其中效果较好的。
select系统调用是经典的I/O多路复用模型,函数原型如下:
intselect(int maxfdp,fd_set *readfds,fd_set *writefds,fd_set *errorfds,structtimeval *timeout);
maxfdp表示最大fd数加1。
readfds、writefds、errorfds分别表示读、写、出错描述符集。有一组宏可以对fd_set进行操作:
FD_ZERO宏可以重置描述符集。
FD_SET宏可以将某个fd置入特定的描述符集合中。
FD_ISSET宏可以判断某个fd是否在某描述符集合中。
timeout表示等待时间,为NULL表示永远等待,直到有准备好的描述符或收到信号;为0表示不等待;如果指定了等待时间,则当捕获到描述符或等待时间到时返回。由于postfix的定时事件和I/O事件都放在event_loop中执行,所以要谨慎设置该参数。
select多路复用模型的并发数受FD_SETSIZE限制,同时期执行方式为循环fd_set集合,效率较低。各个类Unix系统上都实现了各自的高效I/O多路复用模型,postfix和其他服务器软件一样,可根据所在的系统选择合适的多路复用模型:
/util/sys_defs.h
1387 #defineEVENTS_STYLE_SELECT 1 /* Traditional BSD select */
1388 #defineEVENTS_STYLE_KQUEUE 2 /* FreeBSD kqueue */
1389 #defineEVENTS_STYLE_DEVPOLL 3 /* Solaris /dev/poll */
1390 #defineEVENTS_STYLE_EPOLL 4 /* Linux epoll */