POSIX 为您的目的定义了一个函数:sigtimedwait()
. 它将暂停调用进程的执行,直到指定集中的信号之一变为未决,或指定的超时到期。它的返回值指示发生了哪些。
在此期间,如果第一个进程提供数据并向第二个进程发送信号,则一切正常。否则,如果它在这段时间内没有收到来自第一个的任何信号,它会做另一件事。
我怎样才能使第二个过程响应这种需求?
第二个过程为sigtimedwait
. 然后它会阻塞预期的信号(通过sigprocmask
),以便在接收到该信号时不会发生默认处置,然后调用sigtimedwait
. 后者的返回值指示是否接收到指定的信号之一(如果是,是哪个),或者函数是否由于其他原因返回 - 通常是因为超时到期。在后一种情况下,errno
可以检查变量以确定它是否确实是超时。上面链接的手册页提供了一些额外的使用说明。
具体来说,您需要两个主要参数:
asigset_t
定义要阻塞和等待的信号。手册页末尾的“另请参阅”部分为您提供相关和类似功能的文档,包括sigsetops(3)
,它告诉您如何操作此类对象。例如,
#include <signal.h>
// ...
sigset_t sigs;
sigemptyset(&sigs);
sigaddset(&sigs, SIGUSER2);
a struct timespec
,其定义在手册页中提供。这个定义应该足以让你想出类似的东西
struct timespec timeout = { .tv_sec = 10 };
根据文档,您可以指定第二个参数,sigtimedwait
好像NULL
您不需要可以通过这种方式传回给您的信息,而您不需要。
您可以使用如上所述已经准备好的信号集来设置信号阻塞,例如:
sigprocmask(SIG_BLOCK, &sigs, NULL);
这似乎有点违反直觉,因为您确实想接收信号,但其效果是阻止已为信号建立的任何处置发生,这与通过sigtimedwait
.
此时,您已准备好调用sigtimedwait()
:
int sig_num = sigtimedwait(&sigs, NULL, &timeout);
如果在指定时间内接收到指定信号之一(仅在此示例中),则结果将是一个信号编号SIGUSER2
,否则为 -1。所以,
if (sig_num == SIGUSER2) {
// I received the signal
// do something ...
} else {
// assert(sig_num == -1);
// I did not receive the signal within the alotted time
// do something else ...
}
您可能会选择假设在未收到信号的情况下发生超时,但最强大的代码会检查errno
以验证:
if (errno == EAGAIN) {
// it was a timeout
} else if (errno = EINTR) {
// a signal outside the set was received
// ... might want to calculate how much wait time is left and try again
// (left as an exercise)
} else {
// some other error occurred
// ... aborting with an error might be best:
perror("signal wait failed unexpectedly");
exit(1);
}