poll(2) - Linux 手册页
名称
poll, ppoll - 等待文件描述符上的事件
概要
#include <poll.h> int poll(struct pollfd *fds, nfds_t nfds, int timeout); #define _GNU_SOURCE /* See feature_test_macros(7) */ #include <poll.h> int ppoll(struct pollfd *fds, nfds_t nfds, const struct timespec *timeout_ts, const sigset_t *sigmask);
描述
poll() 执行与 select(2) 类似的任务:它等待一组文件描述符中的一个变为可用于执行 I/O 操作。
要监视的文件描述符集合在 fds 参数中指定,这是一个如下结构的数组
-
struct pollfd { int fd; /* file descriptor */ short events; /* requested events */ short revents; /* returned events */ }; - 调用者应在 nfds 中指定 fds 数组中的项目数。
字段 fd 包含一个打开文件的文件描述符。如果该字段为负数,则相应的 events 字段将被忽略,并且 revents 字段返回零。(这提供了一种简单的方法来忽略单个 poll() 调用中的文件描述符:只需取反 fd 字段即可。)
字段 events 是一个输入参数,一个位掩码,指定应用程序对文件描述符 fd 感兴趣的事件。如果该字段指定为零,则将忽略 fd 的所有事件,并且 revents 返回零。
字段 revents 是一个输出参数,由内核填充实际发生的事件。在 revents 中返回的位可以包括 events 中指定的任何位,或者 POLLERR、POLLHUP 或 POLLNVAL 中的一个值。(这三个位在 events 字段中无意义,并且每当相应条件为真时,将在 revents 字段中设置。)
如果对于任何文件描述符没有请求的事件(也没有错误)发生,则 poll() 会阻塞,直到发生其中一个事件。
timeout 参数指定 poll() 将阻塞的最小毫秒数。(此间隔将向上舍入到系统时钟粒度,并且内核调度延迟意味着阻塞间隔可能会超出少量。)在 timeout 中指定负值表示无限超时。指定零的 timeout 将导致 poll() 立即返回,即使没有文件描述符准备就绪。
events 和 revents 中可以设置/返回的位在 <poll.h> 中定义
- POLLIN
有数据可读。
- POLLPRI
有紧急数据可读(例如,TCP 套接字上的带外数据;分组模式下的伪终端主设备在从设备中看到了状态更改)。
- POLLOUT
现在写入将不会阻塞。
- POLLRDHUP (自 Linux 2.6.17 起)
流套接字对等方关闭连接,或关闭连接的写入半部分。为了获得此定义,必须在包含 *任何* 头文件之前定义 _GNU_SOURCE 功能测试宏。
- POLLERR
错误条件(仅输出)。
- POLLHUP
挂断(仅输出)。
- POLLNVAL
无效请求:fd 未打开(仅输出)。
- 在用 _XOPEN_SOURCE 定义编译时,还有以下内容,它们不会传递比上述位更多的信息
- POLLRDNORM
等同于 POLLIN。
- POLLRDBAND
优先级带数据可以读取(在 Linux 上通常未使用)。
- POLLWRNORM
等同于 POLLOUT。
- POLLWRBAND
可以写入优先级数据。
- Linux 也知道,但不使用 POLLMSG。
ppoll()
- poll() 和 ppoll() 之间的关系类似于 select(2) 和 pselect(2) 之间的关系:与 pselect(2) 一样,ppoll() 允许应用程序安全地等待,直到文件描述符变为就绪或捕获信号为止。
除了 timeout 参数的精度差异外,以下 ppoll() 调用
ready = ppoll(&fds, nfds, timeout_ts, &sigmask);
等同于原子性地执行以下调用sigset_t origmask; int timeout; timeout = (timeout_ts == NULL) ? -1 : (timeout_ts.tv_sec * 1000 + timeout_ts.tv_nsec / 1000000); sigprocmask(SIG_SETMASK, &sigmask, &origmask); ready = poll(&fds, nfds, timeout); sigprocmask(SIG_SETMASK, &origmask, NULL);有关为什么需要 ppoll() 的解释,请参阅 pselect(2) 的描述。如果 sigmask 参数指定为 NULL,则不执行任何信号掩码操作(因此 ppoll() 与 poll() 唯一的区别在于 timeout 参数的精度)。
timeout_ts 参数指定 ppoll() 将阻塞的时间上限。此参数是指向以下结构的指针
-
struct timespec { long tv_sec; /* seconds */ long tv_nsec; /* nanoseconds */ }; - 如果 timeout_ts 指定为 NULL,则 ppoll() 可以无限期地阻塞。
返回值
成功时,返回一个正数;这是具有非零 revents 字段的结构的数量(换句话说,那些报告事件或错误的描述符)。值为 0 表示调用超时且没有文件描述符准备就绪。发生错误时,返回 -1,并且设置 errno 适当的值。
错误
- EFAULT
作为参数传递的数组不包含在调用程序的地址空间中。
EINTR
在请求的任何事件发生之前发生了信号;请参阅 signal(7)。
EINVAL
nfds 值超过 RLIMIT_NOFILE 值。
ENOMEM
没有空间来分配文件描述符表。
版本
poll() 系统调用是在 Linux 2.1.23 中引入的。在缺乏此系统调用的旧内核上,glibc(以及旧的 Linux libc)poll() 包装器函数使用 select(2) 提供仿真。
ppoll() 系统调用是在内核 2.6.16 中添加到 Linux 中的。ppoll() 库调用是在 glibc 2.4 中添加的。
符合
poll() 符合 POSIX.1-2001。ppoll() 是 Linux 特有的。
说明
一些实现定义了非标准常量 INFTIM,其值为 -1,用于作为 poll() 的 timeout。此常量未在 glibc 中提供。
有关如果由 poll() 监视的文件描述符在另一个线程中关闭时可能发生的情况的讨论,请参阅 select(2)。
Linux 注意
- Linux ppoll() 系统调用会修改其 timeout_ts 参数。但是,glibc 包装器函数通过使用传递给系统调用的超时参数的局部变量来隐藏此行为。因此,glibc ppoll() 函数不会修改其 timeout_ts 参数。
错误
请参阅 select(2) 的 BUGS 部分中的关于虚假就绪通知的讨论。
参见
select(2), select_tut(2), time(7)