1.函数原型
#include <signal.h>
int sigsuspend(const sigset_t *sigmask);
返回值:-1,并将errno设置为 EINTR
|
sigsuspend 函数将进程的信号屏蔽字设置为 sigmask 指向的值。在捕捉到一个信号或发生了一个会终止该进程的信号之前,该进程被挂起。如果捕捉到一个信号而且从该信号处理程序返回,则sigsuspend返回,在返回之前,将进程的信号屏蔽字设置为调用sigsuspend之前的值。
注意,此函数没有成功返回值。如果它返回到调用者,则总是返回-1,并将 errno 设置为EINTR(表示一个被中断的系统调用)。
2.实例代码 1 (对原文代码稍有修改)
下面的程序显示了保护临界区,使其不被特定信号中断的方法。
#include <stdio.h>
#include <stdlib.h>
#include <signal.h>
#include <errno.h>
static void sig_int(int);
static void sig_usr2(int);
void pr_mask(const char *str)
{
sigset_t sigset;
int errno_save;
errno_save = errno; /* we can be called by signal handlers */
if (sigprocmask(0, NULL, &sigset) < 0)
perror("sigprocmask error");
printf("mask: %s", str);
if (sigismember(&sigset, SIGINT)) printf("SIGINT ");
if (sigismember(&sigset, SIGQUIT)) printf("SIGQUIT ");
if (sigismember(&sigset, SIGUSR1)) printf("SIGUSR1 ");
if (sigismember(&sigset, SIGUSR2)) printf("SIGUSR2 ");
if (sigismember(&sigset, SIGALRM)) printf("SIGALRM ");
/* remaining signals can go here */
printf("n");
errno = errno_save;
}
int main(void)
{
sigset_t newmask, oldmask, waitmask;
pr_mask("program start: ");
if (signal(SIGINT, sig_int) == SIG_ERR)
perror("signal(SIGINT) error");
if (signal(SIGUSR2, sig_usr2) == SIG_ERR)
perror("signal(SIGUSR2) error");
sigemptyset(&waitmask);
sigaddset(&waitmask, SIGUSR1);
sigemptyset(&newmask);
sigaddset(&newmask, SIGINT);
sigaddset(&newmask, SIGUSR2);
/*
* Block SIGINT and save current signal mask.
*/
if (sigprocmask(SIG_BLOCK, &newmask, &oldmask) < 0)
perror("SIG_BLOCK error");
/*
* Critical region of code.
*/
pr_mask("in critical region: ");
/*
* Pause, allowing all signals except SIGUSR1.
*/
if (sigsuspend(&waitmask) != -1)
perror("sigsuspend error");
pr_mask("after return from sigsuspend: ");
/*
* * Reset signal mask which unblocks SIGINT.
* */
if (sigprocmask(SIG_SETMASK, &oldmask, NULL) < 0)
perror("SIG_SETMASK error");
/*
* * And continue processing ...
* */
pr_mask("program exit: ");
exit(0);
}
static void sig_int(int signo)
{
printf("***************************************n");
pr_mask("start sig_int: ");
raise(SIGUSR2);
pr_mask("exit sig_int: ");
printf("***************************************n");
}
static void sig_usr2(int signo)
{
pr_mask("in sig_usr2: ");
}
|
编译后运行,结果如下:
[liumin@localhost sigsuspend_1]$ ./m
mask: program start:
mask: in critical region: SIGINT SIGUSR2 //程序停在这里,然后键入中断字符
***************************************
mask: start sig_int: SIGINT SIGUSR1
mask: in sig_usr2: SIGINT SIGUSR1 SIGUSR2
mask: exit sig_int: SIGINT SIGUSR1
***************************************
mask: after return from sigsuspend: SIGINT SIGUSR2 //从sigsuspend返回后,信号屏蔽字恢复为调用sigsuspend之前的值。
mask: program exit:
[liumin@localhost sigsuspend_1]$
|
实例代码 2:
使用 sigsuspend 函数,等待一个信号处理程序设置一个全局变量。下面的程序用于捕捉中断信号和退出信号,但是希望仅当捕捉到退出信号时,才唤醒主例程。
#include <stdio.h>
#include <stdlib.h>
#include <signal.h>
volatile sig_atomic_t quitflag; /* set nonzero by signal handler */
/* one signal handler for SIGINT and SIGQUIT */
static void sig_handler(int signo)
{
if (signo == SIGINT)
printf("ninterruptn");
else if (signo == SIGQUIT)
quitflag = 1; /* set flag for main loop */
}
int main(int argc, char *argv[])
{
sigset_t newmask, oldmask, zeromask;
if (signal(SIGINT, sig_handler) == SIG_ERR)
perror("signal(SIGINT) error");
if (signal(SIGQUIT, sig_handler) == SIG_ERR)
perror("signal(SIGQUIT) error");
sigemptyset(&newmask);
sigemptyset(&zeromask);
sigaddset(&newmask, SIGQUIT);
/* Block SIGQUIT and save current signal mask */
if (sigprocmask(SIG_BLOCK, &newmask, &oldmask) != 0)
perror("sigprocmask SIG_BLOCK error");
while (quitflag == 0)
sigsuspend(&zeromask);
quitflag = 0;
/* Reset signal mask which unblocks SIGQUIT */
if (sigprocmask(SIG_SETMASK, &oldmask, NULL) != 0)
perror("sigprocmask SIG_SETMASK error");
exit(0);
}
|
编译运行结果:
[liumin@localhost sigsuspend_2]$ ./m // Ctrl + C interrupt // Ctrl + C interrupt // Ctrl + C interrupt // Ctrl + 退出 [liumin@localhost sigsuspend_2]$
|
阅读(2528) | 评论(0) | 转发(0) |