IO 多路复用(三)poll 函数

2020-12-18  本文已影响0人  Tubetrue01

引言

据说 poll 函数起源于 SVR3,最初局限于流设备。而到了 SVR4 取消了这种限制,允许 poll 工作在任何描述符上。 功能与 select 类似,不过在处理流设备时,它能够提供额外的信息。

1.0 函数原型

#include <sys/poll.h>

int poll(struct pollfd *fdarray, nfds_t nfds, int timeout);

1.1 参数

fdarray

该参数是指向一个结构数组第一个元素的指针。每个数组元素都是一个 pollfd 结构体,用于指定测试某个描述符 fd 的条件。我们看一下它的原型:

struct pollfd 
{
  int   fd;       /* descriptor to check */
  short events;   /* events of interest on fd */
  short revents;  /* events that occurred on fd */
};

这就理解为,把描述符、关心的事件、事件的状态封装成了一个对象。这些对象组成起来就构成了这个结构数组。它避免了像 select 函数中间三个参数都是值-结果参数。

说明

值-结果参数: 该参数在函数调用的时候作为值传递给函数,函数执行完毕之后将执行结果保存到该参数中,所谓一参两用。值-结果参数一定要传指针。

对于 events 跟 revents 参数,它们每一个都由指定某个特定条件的一位或多位构成,下面是一些常值:

常值 是否作为 events 的输入 是否作为 revents 结果 说明
POLLIN \bullet \bullet 普通或优先级带数据可读
POLLRDNORM \bullet \bullet 普通数据可读
POLLRDBAND \bullet \bullet 优先级带数据可读
POLLPRI \bullet \bullet 高优先级数据可读
POLLOUT \bullet \bullet 普通数据可写
POLLWRNORM \bullet \bullet 普通数据可写
POLLWRBAND \bullet \bullet 优先级带数据可写
POLLERR \circ \bullet 发生错误
POLLHUP \circ \bullet 发生挂起
POLLNVAL \circ \bullet 描述符不是一个打开的文件

我们需要记住 poll 识别三类数据:普通、优先级带、高优先级。

补充:

POLLIN 可被定义为 POLLRDNORM 和 POLLRDBAND 的逻辑或;POLLOUT 等同于 POLLWRNORM。

还要注意的是,如果是 TCP 和 UDP 套接字,一下的条件会引起 poll 返回特定的 revent (然而不性的是, POSIX 在其 poll 的定义中留了许多空洞,会造成多种方式可返回相同的条件)。

nfds

该参数指定了结构数组(也就是第一个参数)中元素的个数。该参数被声明为:nfds_t 类型,对应的其实是:unsigned int。

timeout

该参数指定了 poll 函数返回前等待多长时间。

INFTIM 常值被定义为一个负值。如果系统不能提供毫秒级精度的定时器,该值就向上舍入到最接近的支持值。

补充:

POSIX 规范要求在头文件 <poll.h> 中定义 INFTIM,不过许多系统仍然把它定义在头文件 <sys/stropts.h> 中。

1.2 返回值

如果不想关心某个描述符,只需要把该描述符对应的 pollfd 结构的 fd 成员设置成一个负值就可以了。poll 函数将会忽略这样的 pollfd 结构的 events 成员,并且返回时,将它的 revents 成员值置为 0。

2.0 注意

对于 poll 函数,就不再需要关心每个进程中最大描述符的数量之类的问题了,因为 poll 函数采用 pollfd 结构体数组的方式传递给内核,并且把传递数组元素的数量给内核的责任交给了调用者。所以,内核也就不在需要知道类似 fd_set 的固定大小的数据类型了。


参考

上一篇 下一篇

猜你喜欢

热点阅读