poll函数提供的功能与select类似,不过在处理流设备时,它能够提供额外的信息。
poll函数原型
#include <poll.h> int poll(struct pollfd *fdarray, unsigned long nfds, int timeout); 返回:就绪描述字的个数,0——超时,-1——出错
poll函数参数介绍
第一个参数是指向一个结构数组第一个元素的指针。每个数组元素都是一个pollfd结构,用于指定测试某个给定描述字fd的条件。
struct pollfd { int fd; /* descriptor to check */ short events; /* events of interest on fd */ short revents; /* events that occurred on fd */ };
要测试的条件由events成员指定,函数在相应的revents成员中返回该描述字的状态。(每个描述字都有两个变量:一个为调用值,另一个为返回结果,从而避免使用值-结果参数。) 这两个成员中的每一个都由指定某个特定条件的一位或多位组合而成。下图列出了用于指定events标志以及测试revents标志的一些常值。
我们将该图分为三个部分:第一部分是处理输入的四个常值,第二部分是处理输出的三个常指,第三部分是处理错误的三个常值。其中第三部分的三个常值不能在events中设置,但是当相应条件存在时就在revents中返回。
poll识别三类数据:普通(normal)、优先级带(priority band)和高优先级(high priority)。这些术语均出自于流的实现。
就TCP和UDP套接口而言,以下条件引起poll返回特定的revent。不幸的是,POSIX在其poll的定义中留了许多空洞(也就是说有多种方法可返回相同的条件)。
(1)所有正规TCP数据和所有UDP数据都被认为是普通数据。
(2)TCP的带外数据被认为是优先级数据。
(3)当TCP连接的读这一半关闭时(例如收到了一个来自对端的FIN),也被认为是普通数据,随后的读操作将返回0.
(4)TCP连接存在错误既可认为是普通数据,也可认为是错误(POLLERR),无论哪种情况,随后的读操作将返回-1,并把errno设置成合适的值。这可用于处理诸如接收到RST或超时发生等条件。
(5)在监听套接口上有新的连接可用既可认为是普通数据,也可认为是优先级数据。大多数实现视之为普通数据。
(6)非阻塞式connect的完成被认为使得相应套接口可写。
结构数组中元素的个数是由nfds参数指定。
timeout参数指定了poll函数返回前等待多长时间。它是一个指定应等待的毫秒数的正值。下图给出了它的可能取值。
INFTIM常值被定义为一个负值。如果系统不提供毫秒级精度的定时器,该值就向上舍入到最接近的支持值。
poll函数的返回值
当发生错误时,poll函数的返回值为-1;若定时器时间到之前没有任何描述字就绪,则返回0;否则返回就绪描述字的个数,即其revents成员值非0的描述字个数。
如果我们不再关心某个特定描述字,那么可以把与它对应的pollfd结构的fd成员设置成一个负值。poll函数将忽略这样的poll结构的events成员,返回时将它的revents成员的值置为0.