poll()系统调用

#include <poll.h>
int poll(struct pollfd fds[], nfds_t nfds, int timeout);
        Returns number of readf file descriptors, 0 on timeout, or -1 on error.

参数fds列出了我们需要poll()来检查的文件描述符。该参数为pollfd结构体数组,其定义如下:

struct pollfd{
    int fd;
    short events;
    short revents;
};

参数nfds指定了数组fds中元素的个数。数据类型nfds_t实际为无符号整型。

pollfd结构体中的eventsrevents字段都是位掩码。调用者初始化events来指定需要为描述符fd做检查的事件。

poll()返回时,revents被设定以此来表示该文件描述符上实际发生的事件。

下表列出了可能会出现在eventsrevents字段中的位掩码。

  • 该表中第一组位掩码(POLLIN, POLLRDNORM, POLLRDBAND, POLLPRI以及POLLRDHUP)同输入事件相关。

  • 下一组掩码(POLLOUT, POLLWRNORM 以及 POLLWRBAND)同输出事件相关。

  • 第三组掩码(POLLERR, POLLHUP 以及 POLLNVAL)是设定在revents字段中用来返回有关文件描述符的附加信息。如果在events中指定了这些位掩码,则者三位将被户卤鹅。

  • 在Linux系统中,poll()不会用到最后一个位掩码POLLMSG

位掩码events中的输入返回到revents描述
POLLIN可读取非高优先级的数据
POLLRDNORM等同于POLLIN
POLLRDBAND可读取优先级数据(Linux中不使用)
POLLPRI可读取高优先级数据
POLLRDHUP对端套接字关闭
——————————————————————————————————
POLLOUT普通数据可写
POLLWRNORM等同于POLLOUT
POLLWRBAND优先级数据可写入
——————————————————————————————————
POLLERR有错误发生
POLLHUP出现挂断
POLLNVAL文件描述符未打开|
——————————————————————————————————
POLLMSGLinux中不使用(SUSv3中未指定) |

如果我们对某个特定的文件描述符上的事件不感兴趣,可以将events设为0。
另外,给fd字段指定一个负值(例如,如果值为非零,取它的相反数)将导致对应的events字段被忽略,且revents字段将总是返回0.

这两种方法都可以用来(也许只是暂时的)关闭单个文件描述符的检查,而不需要重新建立整个fds列表。

下面列出的是关于poll()的Linux实现:

  • POLLINPOLLRDNORM是同义词。
  • POLLIUTPOLLWRNORM是同义词。
  • 一般来说,POLLRDBAND是不被使用的,也就是说它在events字段中被忽略,也不会被设定到revents字段中去。

唯一用到POLLRDBAND的地方是在实现DECnet网络协议的代码中(已过时)。

  • 必须定义_XOPEN_SOURCE测试宏,这样才能在头文件<poll.h>中得到常量POLLRDNORMPOLLRDBANDPOLLWRNORM以及POLLWRBAND的定义。
  • POLLRDHUP是Linux专有的标志位。要在头文件<poll.h>中得到它,必须定义_GNU_SOURCE测试宏。
  • 如果指定的文件描述符在调用poll()时关闭了,则返回POLLNVAL

总结以上要点,poll()真正关心的标志位就是POLLINPOLLOUTPOLLPRIPOLLRDHUPPOLLHUP以及POLLERR

timeout参数

参数timeout决定了poll()的阻塞行为,具体如下:

  • 如果timeout 等于 -1poll()一直阻塞直到 fds数组中列出的文件描述符有一个达到就绪态(定义在对应的events 字段中)或者捕获到一个信号。
  • 如果timeout等于0,poll()不会阻塞——只是执行一次检查看看哪个文件描述符处于就绪态。
  • 如果timeout大于0,poll()至多阻塞timeout毫秒,直到fds列出的文件描述符中有一个达到就绪态,或者直到捕获到一个信号为止。

poll()的返回值

  • 返回-1表示有错误发生。一种可能的错误是EINTR,表示该调用被一个信号处理例程中断。 (poll()绝对不会自动恢复)
  • 返回0表示该调用在任意一个文件描述符称为就绪态之前就超时了。
  • 返回正整数表示有一个或多个文件描述符处于就绪态了。返回值表示数组fds中拥有非零revents字段的pollfd结构体数量。

注意select()poll()返回正整数时的细小差别。
如果一个文件描述符在返回的描述符集中出现了不止依次,select()会将同一个文件描述符计数多次。
poll()返回的是就绪的文件描述符个数,且一个文件描述符只会统计一次,就算在相应的revents字段中设定了多个位掩码也是如此。

补充

  1. 在描述符数量很多时,poll()效率比select()性能明显更好。
  2. poll()select()在大多数系统上不会自动重启,SA_RESTART选项对它们不起作用(见APUE第3版p409)。

参考书籍

  1. UNIX环境高级编程 第3版
  2. Linux/UNIX系统编程手册
  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 打赏
    打赏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

barbyQAQ

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值