名称

zmq_ppoll - 带信号掩码的输入/输出多路复用

概要

int zmq_ppoll (zmq_pollitem_t '*items', int 'nitems', long 'timeout', const sigset_t '*sigmask');

说明

zmq_poll()zmq_ppoll() 之间的关系类似于 poll(2) 和 ppoll(2) 之间以及 select(2) 和 pselect(2) 之间的关系:zmq_ppoll() 允许应用程序安全地等待,直到文件描述符就绪或直到捕获到信号。

当使用 'sigmask' 设置为 NULL 的 zmq_ppoll() 时,其行为与 zmq_poll() 完全相同。有关更多信息,请参见 zmq_poll

要充分利用 zmq_ppoll(),必须构造并传递指向信号掩码的非 NULL 指针给 'sigmask'。有关更多详细信息,请参见 sigprocmask(2)。完成此操作后,在实际的 ppoll()(或 pselect(),参见下面的注意)系统调用内部,会执行一个由三个步骤组成的原子操作:1. 当前信号掩码被替换为 'sigmask' 指向的信号掩码。2. 执行实际的 poll() 调用。3. 恢复原始信号掩码。由于这些操作是原子执行的,因此在更改信号掩码的调用和 poll/select 系统调用之间没有竞态条件的发生机会。这意味着只有在此(原子)调用期间,我们可以解除阻塞某些信号,以便仅在此时处理它们,而不是在调用之外。这意味着实际上,我们将我们的轮询器扩展为一个函数,它不仅监视套接字的变化,还监视“POSIX 信号套接字”以获取传入的信号。在其他时间,这些信号将被阻塞,并且我们无需处理这些其他时间发生的系统调用中断。

注意
zmq_ppoll() 函数可能使用除了 ppoll() 之外的操作系统接口来实现或模拟,因此可能受到这些接口的限制,其方式可能未在此文档中定义。
注意
Windows 上没有 ppollpselect,因此 Windows 构建中不支持 zmq_ppoll()。它仍然可以调用,但其 'sigmask' 是 void 指针类型(因为 'sigset_t' 在 Windows 上也不可用),并且 zmq_ppoll() 将返回一个错误(参见下面的错误部分)。

线程安全

zmq_pollitem_t 数组只能由将要或正在调用 zmq_ppoll 的线程使用。

如果一个套接字包含在多个 zmq_pollitem_t 数组中,且每个数组由不同的线程拥有,则套接字本身需要是线程安全的(例如 Server, Client 等)。否则,行为是未定义的。

返回值

成功完成后,zmq_ppoll() 函数应返回 'revents' 中已通知事件的 zmq_pollitem_t 结构的数量,如果没有事件通知则返回 0。失败时,zmq_ppoll() 应返回 -1 并将 'errno' 设置为下面定义的一个值。

错误

ETERM

'items' 数组中至少一个成员引用了一个相关的 0MQ 'context' 已终止的 'socket'。

EFAULT

提供的 'items' 无效 (NULL)。

EINTR

在任何事件可用之前,操作被信号传递中断。

EINTR

在任何事件可用之前,操作被信号传递中断。

ENOTSUP

在此构建中未激活 zmq_ppoll()

示例

在 0MQ 套接字和标准套接字上无限期轮询输入事件。

参见 zmq_poll示例部分。只需将 zmq_poll 调用替换为 zmq_ppoll,并为 'sigmask' 参数添加一个 NULL 参数即可。

zmq_ppoll 期间处理 SIGTERM(否则阻塞它)。
// simple global signal handler for SIGTERM
static bool sigterm_received = false;
void handle_sigterm (int signum) {
    sigterm_received = true;
}

// set up signal mask and install handler for SIGTERM
sigset_t sigmask, sigmask_without_sigterm;
sigemptyset(&sigmask);
sigaddset(&sigmask, SIGTERM);
sigprocmask(SIG_BLOCK, &sigmask, &sigmask_without_sigterm);
struct sigaction sa;
memset(&sa, '\0', sizeof(sa));
sa.sa_handler = handle_sigterm;

// poll
zmq_pollitem_t items [1];
// Just one item, which refers to 0MQ socket 'socket' */
items[0].socket = socket;
items[0].events = ZMQ_POLLIN;
// Poll for events indefinitely, but also exit on SIGTERM
int rc = zmq_poll (items, 2, -1, &sigmask_without_sigterm);
if (rc < 0 && errno == EINTR && sigterm_received) {
  // do your SIGTERM business
} else {
  // do your non-SIGTERM error handling
}

另请参阅

您的操作系统关于 poll() 系统调用的文档。

作者

此页面由 0MQ 社区编写。要进行更改,请阅读 0MQ 贡献政策,网址为 https://zeromq.cn/how-to-contribute/