《unix高级环境编程》信号——信号集

来源:互联网 发布:cdn是什么 知乎 编辑:程序博客网 时间:2024/05/18 09:42

信号集

          信号集是表示多个信号的数据类型,这里的信号集数据类型是 sigset_t,包含五个处理信号集的函数:

/* 信号集 */#include <signal.h>int sigemptyset(sigset_t *set);//初始化由set所指向的信号集,清空信号集;int sigfillset(sigset_t *set);//初始化由set所指向的信号集,使其包括所有信号;int sigaddset(sigset_t *set, int signo);//把指定的信号signo添加到由set所指的信号集中;int sigdelset(sigset_t *set, int signo);//把指定的信号signo从由set所指定的信号集中删除;//前面四个函数返回值:若成功则返回0,若出错则返回-1;int sigismember(const sigset_t *set, int signo);//判断指定的信号signo是否在由set所指的信号集中;//返回值:若为真则返回1,若为假则返回0,若出错则返回-1;/* * 说明: * 所有应用程序使用信号集之前,要对该信号集调用sigemptyset或sigfillset一次; */

sigprocmask 函数

        在前面我们提到,task_struct  结构有一个blocked 成员(我们称之为“信号屏蔽字”),它指定了进程阻塞的信号,被阻塞的信号将不能被递送给进程,直到进程解除阻塞。在信号被阻塞时,内核将其放置到待决列表上。如果同一个信号在阻塞期间被发送了多次,则在待决列表中只放置一次。也就是说,不管发送了多少相同的信号,在进程删除阻塞后,都只会接收到一个信号。调用函数sigprocmask可以检测或更改其信号屏蔽字。在调用 sigprocmask 后如果有任何未决的、不再阻塞的信号,则在sigprocmask 返回前,至少会将其中一个信号递送给该进程。

/* sigprocmask 函数 *//* * 函数功能:检查或更改信号屏蔽字,也可同时执行这两个操作; * 返回值:若成功则返回0,若出错则返回-1; * 函数原型: */#include <signal.h>int sigprocmask(int how, const sigset_t *set, sigset_t *oset);/* * 说明: * 若oset是非空指针,那么进程的当前信号屏蔽字通过oset返回; * 若set是非空指针,则参数how指示如何修改当前信号屏蔽字; * 若set是空指针,则不改变该进程的信号屏蔽字,how的值就没有意义; * 参数how可选以下值: * (1)SIG_BLOCK   该进程新的信号屏蔽字是其当前信号屏蔽字和set指向信号集的并集。set包含了我们希望阻塞的附加信号; * (2)SIG_UNBLOCK 该进程新的信号屏蔽字是其当前信号屏蔽字和set指向信号集补集的交集;set包含我们希望解除阻塞的附加信号; * (3)SIG_SETMASK 该进程新的信号屏蔽字将被set指向的信号集的值所代替; *  SIG_BLOCK是"或"操作,而SIG_SETMASK则是赋值操作; *  注意:SIGKILL 和 SIGSTOP 信号是不能阻塞的; */

sigpending 函数

          sigpending 函数返回信号集,其中的各个信号对于调用进程是阻塞的而不能传递,该信号集通过set参数返回。

/* sigpending函数 *//* * 函数功能:返回信号集; * 返回值:若成功则返回0,若出错则返回-1; * 函数原型: */#include <signal.h>int sigpending(sigset_t *set);

测试程序:

#include "apue.h"#include <sys/wait.h>#include <unistd.h>#include <sys/types.h>#include <errno.h>#include <signal.h>static void sig_quit(int signo);int main(){    sigset_t    newmask,oldmask,pendmask;    if(signal(SIGQUIT,sig_quit) == SIG_ERR)    {        err_sys("signal() error");        exit(-1);    }    //初始化信号集    sigemptyset(&newmask);    //添加一个SIGQUIT信号    sigaddset(&newmask,SIGQUIT);    //将newmask信号集设置为阻塞,原信号集保存在oldmask中    if(sigprocmask(SIG_BLOCK,&newmask,&oldmask) == -1)    {        err_sys("SIG_BLOCK error");        exit(-1);    }    sleep(5);    //获取阻塞的信号集    if(sigpending(&pendmask) == -1)    {        err_sys("sigpending() error");        exit(-1);    }    //判断SIGQUIT是否是阻塞的    if(sigismember(&pendmask,SIGQUIT))        printf("\nSIGQUIT is pending.\n");    //恢复原始的信号集    if(sigprocmask(SIG_SETMASK,&oldmask,NULL) == -1)    {        err_sys("SIG_SETMASK error");        exit(-1);    }    printf("SITQUIT unblocked\n");    sleep(5);    exit(0);}static void sig_quit(int signo){    printf("caught SIGQUIT.\n");    if(signal(SIGQUIT,SIG_DFL) == SIG_ERR)    {        err_sys("can't reset SIGQUIT");        exit(-1);    }}
输出结果:

$ ./sigset ^\SIGQUIT is pending.caught SIGQUIT.SITQUIT unblocked$ ./sigset ^\^\^\^\^\^\SIGQUIT is pending.caught SIGQUIT.SITQUIT unblocked
       在程序第二次 sleep 时,产生了多个SIGQUIT 信号,此时被pending,解除了 mask 后,只产生了一次action,也说明了在同一时刻产生多次同一种信号,不会对信号排队。

参考资料:

《UNIX高级环境编程》

0 0
原创粉丝点击