即便通过select()或者 poll()函数复用事件通知具有突出的优点,不过,其他具有类似功能的函数实现也可以达到同样的性能。然而,这些实现在跨平台方面没有实现标准化。你必须在使用这些特定函数实现同丧失可移植性之间进行权衡。我们现在就讨论一下两个替代方法:Solaris系统下的/dev/poll和FreeBSD系统下的kqueue。
如你看到的那样,以上两种实现通过以下办法提高了关键的性能,实际上,在现实的应用环境中,开发人员几乎总是针对 select()或者 poll()函数连续地采用同一fds。在每次采用同样参数的时候为了消除这一重复性所带来的麻烦,本来需要检查的fds的就被缓冲了。这一措施在监视大量fds的时候效率特别高,因为某些select()和poll()实现存在可伸缩性方面的问题。
在Solaris 7系统上,Sun引入了/dev/poll设备。在使用 /dev/poll的时候,你首先要打开/dev/poll作为一个普通文件。然后构造pollfd结构,方式同普通的poll()函数调用一样。这些pollfd结构随后写入到打开的 /dev/poll 文件描述符。在打开句柄的生存周期内, /dev/poll会根据pollfd结构返回事件(注意,pollfd结构内的事件字段中的特定POLLREMOVE将从/dev/poll的列表中删除对应的fd)。通过调用特定的ioctl (DP_POLL) 和dvpoll,程序就可以从/dev/poll获得需要的信息。在使用dvpoll结构的情况下,发生的事件就可以被检测到了。
增加/dev/poll对Linux 2.4系列的支持是有相应补丁程序的,但是,目前这些补丁程序还没有被主流Linux内核接受。在FreeBSD网站上,你可以查阅Solaris、Red Hat以及其他操作系统的有关手册信息了解这方面的情况。
在FreeBSD 4.1中推出。FreeBSD的kqueue
API设计为比其他对应函数提供更为广泛的事件通知能力。kqueue API提供了一套通用过滤器,可以模仿poll()语法(EVFILT_READ和EVFILT_WRITE)。不过,它还实现了文件系统变化(EVFILT_VNODE)、进程状态变更(EVFILT_PROC)和信号交付(EVFILT_SIGNAL)的有关通知。要了解有关kqueue的详细情况可以从BSDCon
2000下载Jonathan Lemon的论文(PDF格式)“Kqueue: A generic and scalable
event notification facility”
为了进一步了解本文所介绍的select()和 poll()方法调用,我建议你阅读W. Richard Stevens 撰写的UNIX环境高级编程一书。