一个进程的信号屏蔽字规定了当前阻塞而不能送递给该进程的信号集。
调用函数sigprocmask可以检测或更改其信号屏蔽字,或者在一个步骤中同时执行检测和更改。
#include
int sigprocmask(int how, const sigset_t *restrict set,sigset_t *restrict oset);
1)若oset不为空,则进程的当前信号屏蔽字通过oset返回
2)若set是一个非空指针,则参数how指示如何修改当前信号屏蔽字。
how
|
说明
|
SIG_BLOCK
|
进程新的信号屏蔽字是其当前信号屏蔽字和set指向信号集的并集
|
SIG_UNBLOCK
|
进程新的信号屏蔽字是其当前信号屏蔽字和set指向信号集补集的交集
|
SIG_SETMASK
|
进程新的信号屏蔽字被set指向的信号集所替代
|
例子1 测试阻塞信号CTRL+C (SIGINT)
-
#include <stdio.h>
-
#include <stdlib.h>
-
#include <signal.h>
-
-
int main(int argc, char *argv[])
-
{
-
sigset_t set;
-
-
sigemptyset(&set);
-
sigaddset(&set,SIGINT);
-
sigprocmask(SIG_SETMASK,&set,NULL);
-
-
sleep(15);
-
-
return 0;
-
}
编译运行:
程序运行后,由于屏蔽了SIGINT信号,当按CTRL+C退出时程序无反应,直到15秒超时后程序退出
-
[root@localhost signal]# gcc -g sigprocmask.c -o sigprocmask
-
[root@localhost signal]# ./sigprocmask
-
^C^C^C^C^C^C^C^C^C^C^C^C^C^C^C^C^C[root@localhost signal]#
在调用sigprocmask后如果有任何未决的、不再阻塞的信号,则在sigprocmask返回前,至少会将其中一个信号递送给该进程。
例子2 测试sigprocmask返回前,至少会将其中一个未决、不再阻塞的信号传递给该进程。
-
#include <stdio.h>
-
#include <stdlib.h>
-
#include <signal.h>
-
-
void sig_int(int signo)
-
{
-
printf("\nreceived SIGINT!\n");
-
}
-
-
int main()
-
{
-
sigset_t newmask,oldmask;
-
-
if(signal(SIGINT,sig_int) == SIG_ERR)
-
perror("signal(SIGINT) error!");
-
sigemptyset(&newmask);
-
sigaddset(&newmask,SIGINT);
-
if(sigprocmask(SIG_BLOCK,&newmask,&oldmask) < 0)
-
perror("sigprocmask(SIG_BLOCK) error!");
-
-
sleep(5);
-
-
if(sigprocmask(SIG_SETMASK,&oldmask,NULL) < 0)
-
perror("sigprocmask(SIG_SETMASK) error!");
-
-
return 0;
-
}
第一个运行./sigprocmask1后,按键CTRL+C,发现没有进入信号处理函数,等待5s后,重新进入sigprocmask,此时会处理原来阻塞未决的CTRL+C信号,此时由于sigprocmask已经将SIGINTR信号设置为不阻塞,所以进程收到SIGINTR信号后进入信号处理函数,并打印出received。
第二次运行./sigprocmask1后,不做任何处理,等待5s后退出。
编译运行:
-
[root@localhost signal]# gcc -g sigprocmask1.c -o sigprocmask1
-
[root@localhost signal]# ./sigprocmask1
-
^C^C
-
received
-
[root@localhost signal]# ./sigprocmask1
-
[root@localhost signal]#
2. sigpending
函数原型:
int sigpending(sigset_t *set); -----------返回当前阻塞的信号集set。
返回值: 成功返回0, 失败返回-1
-
#include <stdio.h>
-
#include <stdlib.h>
-
#include <signal.h>
-
static void sig_quit(int);
-
-
int main(void)
-
{
-
sigset_t newmask,oldmask,pendmask;
-
-
if(signal(SIGQUIT, sig_quit) == SIG_ERR)
-
printf("can't catch SIGQUIT\n");
-
-
sigemptyset(&newmask);
-
sigaddset(&newmask, SIGQUIT);
-
-
if(sigprocmask(SIG_BLOCK, &newmask, &oldmask) < 0)
-
printf("SIG_BLOCK error\n");
-
-
sleep(5);
-
-
if(sigpending(&pendmask) < 0) {
-
printf("sigpending error\n");
-
}
-
if(sigismember(&pendmask,SIGQUIT))
-
printf("\nSIGQUIT pending\n");
-
/*这个时候在执行sigprocmask(SIG_SETMASK, &oldmask,NULL),然后说如果在休眠期间产生过退出信号,那个这个时候这个信号是未决的,但是这个时候sigprocmask要让信号不阻塞,根据sigprocmask的意义,在调用sigprocmask函数返回之前,如果有未决的信号,则会有一个信号递送到调用进程,也就是说SIGQUIT信号是在sigprocmask返回之前,送到了信号处理函数,信号处理函数处理结束后,sigprocmask才返回。
*/
-
if(sigprocmask(SIG_SETMASK, &oldmask,NULL) < 0)
-
printf("SIG_SETMASK error\n");
-
printf("SIGQUIT unblocked\n");
-
-
return 0;
-
}
-
-
static void sig_quit(int signo)
-
{
-
printf("caught SIGQUIT\n");
-
sleep(3);
-
printf("after sleep 3 seconds\n");//延时3秒,为了看得更清楚--信号处理函数是在sigprocmask返回之前调用的。
-
if(signal(SIGQUIT, SIG_DFL) == SIG_ERR)
-
printf("can't reset SIGQUIT\n");
-
}
-
gwwu@hz-dev2.aerohive.com:~/test/signal>gcc -g sigpending.c -o sigpending
-
gwwu@hz-dev2.aerohive.com:~/test/signal>./sigpending
-
^\
-
SIGQUIT pending
-
caught SIGQUIT
-
after sleep 3 seconds
-
SIGQUIT unblocked
阅读(1711) | 评论(0) | 转发(0) |