安装信号处理程序,并导致信号被传递(使用alarm()、setitimer() 或timer_create()+timer_settime()),这样信号的传递将中断sem_wait() 调用。
考虑这个示例程序:
#define _POSIX_C_SOURCE 200809L
#include <stdlib.h>
#include <unistd.h>
#include <string.h>
#include <signal.h>
#include <semaphore.h>
#include <stdio.h>
#include <errno.h>
static void dummy_handler(int signum)
{
}
static int install_dummy_handler(int signum)
{
struct sigaction act;
memset(&act, 0, sizeof act);
sigemptyset(&act.sa_mask);
act.sa_handler = dummy_handler;
act.sa_flags = 0;
return sigaction(signum, &act, NULL);
}
static const char *errname(const int errnum)
{
switch (errnum) {
case EINTR: return "EINTR";
case EINVAL: return "EINVAL";
default: return "(other)";
}
}
int main(void)
{
sem_t s;
if (install_dummy_handler(SIGALRM) == -1) {
fprintf(stderr, "Cannot install ARLM signal handler: %s.\n", strerror(errno));
return EXIT_FAILURE;
}
sem_init(&s, 0, 0);
alarm(1);
if (sem_wait(&s) == -1) {
const int errnum = errno;
printf("sem_wait() failed with errno == %s (%d; %s).\n",
errname(errnum), errnum, strerror(errnum));
} else
printf("sem_wait() succeeded.\n");
return EXIT_SUCCESS;
}
在main() 中,我们为 SIGALRM 信号安装了一个信号处理程序。信号处理函数是否做任何事情都没有关系,因为正是 信号的传递 导致“慢”系统调用返回 EINTR 错误。 (只要在安装该处理程序时不使用 SA_RESTART 标志。如果您查看install_dummy_handler() 中的act.sa_mask,您会发现我们根本没有使用任何标志。所有标志和sigaction() 的用法在 man 2 sigaction 手册页中有描述。)
在main()中,我们首先初始化我们的信号量,然后设置一秒钟的闹钟。当真正的挂钟时间过去时,会发出 SIGALRM 信号。
请注意,虽然 SIGALRM 非常适合本示例和类似目的,但您可能希望使用 POSIX per-process interval timers 代替。
接下来,我们只需在信号量上调用sem_wait(),并检查结果。实际上,如果您使用例如编译和运行上述 example.c
gcc -Wall -O2 example.c -lpthread -o example
./example
程序将输出
sem_wait() failed with errno == EINTR (4; Interrupted system call).
一秒钟后。