sigemptyset,sigfillset,sigaddset,sigdelset,sigismember,sigprocmask,sigpendmask作用

SYNOPSIS
       #include <signal.h>

       int sigemptyset(sigset_t *set);

       int sigfillset(sigset_t *set);

       int sigaddset(sigset_t *set, int signum);

       int sigdelset(sigset_t *set, int signum);

       int sigismember(const sigset_t *set, int signum);

以上都是信号集操作函数,如果是glibc,还额外提供了以下3个函数

       int sigisemptyset(sigset_t *set);

       int sigorset(sigset_t *dest, sigset_t *left, sigset_t *right);

       int sigandset(sigset_t *dest, sigset_t *left, sigset_t *right);

描述:

  查看linux3.13 signal.h文件源码,一共有31个用户可用的信号,信号集用每一位对应于一个信号。

  sigemptyset

    初始化信号集set,将指定的信号集set清空,即set的值为0。

  sigfillset

    初始化信号集set,将指定的信号集set全部置位,即set值为0x7FFFFFFF

  sigaddset

    将信号signum对应于信号集set的那一位置位

  sigdelset

    将信号signum对应于信号集set的那一位清零

  以上4个函数成功返回0,否则返回-1

  sigismember

    查询信号signum是否在信号集中置位了。如果置位了,返回1,否则返回0

 glibc的扩展信号集操作函数:

  sigisemptyset

    信号集set是否清空了

  sigorset

    获得信号集left,right的并集,存放到dest

  sigandset

    获得信号集left,right的交集,存放到dest

扩展函数的测试程序:

 1     sigset_t sigdest, sigleft, sigright;
 2
 3     sigemptyset(&sigdest);
 4     sigemptyset(&sigleft);
 5     sigemptyset(&sigright);
 6
 7     sigaddset(&sigleft, SIGALRM);
 8     sigaddset(&sigleft, SIGINT);
 9
10     sigaddset(&sigright, SIGALRM);
11     sigaddset(&sigright, SIGQUIT);
12
13
14     printf("\nSIG union\n");
15     sigorset(&sigdest, &sigleft, &sigright);
16     if ( sigismember(&sigdest, SIGALRM ) )
17     {
18         printf("SIGALRM\n");
19     }
20     if ( sigismember(&sigdest, SIGINT ) )
21     {
22         printf("SIGINT\n");
23     }
24     if ( sigismember(&sigdest, SIGQUIT ) )
25     {
26         printf("SIGQUIT\n");
27     }
28
29     printf("\nSIG intersection\n");
30     sigemptyset(&sigdest);
31     sigandset(&sigdest, &sigleft, &sigright);
32     if ( sigismember(&sigdest, SIGALRM ) )
33     {
34         printf("SIGALRM\n");
35     }
36     if ( sigismember(&sigdest, SIGINT ) )
37     {
38         printf("SIGINT\n");
39     }
40     if ( sigismember(&sigdest, SIGQUIT ) )
41     {
42         printf("SIGQUIT\n");
43     }

运行结果:

SIG union
SIGALRM
SIGINT
SIGQUIT

SIG intersection
SIGALRM

sigprocmask函数

SYNOPSIS
       #include <signal.h>

       int sigprocmask(int how, const sigset_t *set, sigset_t *oldset);

根据动作how修改或者获取,或者修改并获取当前调用进程的信号掩码(一个信号集)。how有一下值可选:

       SIG_BLOCK
              将阻塞信号集设置为当前阻塞信号集oldset和指定的信号集的并集,相当于一个或操作

       SIG_UNBLOCK
              根据设置的信号集set,将当前阻塞信号集oldset对应的位清除,使其不阻塞。

       SIG_SETMASK
              将阻塞信号集设置为指定信号集set。

  •   如果oldset不为NULL,则函数返回时,oldset指向的内容为调用函数前进程信号掩码,也就是可以获取函数调用之前的信号掩码。
  •   如果set为NULL,则进程信号掩码不会更改,how将被忽略,如果此时oldset不为空,则可以获得之前的信号掩码。

需要注意的是sigprocmask只对单线程或者单进程有效,多线程中要使用thread_sigmask函数。还有就是SIGSTOP,SIGKILL是不会被阻塞的,即使指定了也会忽略。

  进程中的每个线程都有其各自独立的signal mask。

  子进程会获得父线程同样的signal mask。

sigpending
SYNOPSIS
       #include <signal.h>

       int sigpending(sigset_t *set);

  sigpending,获得调用进程挂起的信号集,所谓挂起就是指有信号发往这个进程,但是此时被阻塞了,等阻塞解除,就会送至进程里面。

下面是一个综合的例子(来自APUE):

 1 static void sig_int(int signo)
 2 {
 3     printf("catch SIGINT\n");
 4     if ( signal(SIGINT, SIG_DFL) == SIG_ERR )
 5     {
 6         perror("signal\n");
 7     }
 8 }
 9
10 int main ( int argc, char *argv[] )
11 {
12     sigset_t newset,oldset,pendmask;
13
14     if ( signal(SIGINT,sig_int) == SIG_ERR )
15     {
16         perror("signal\n");
17     }
18
19     if ( sigemptyset(&newset) < 0 )
20     {
21         perror("sigempty\n");
22     }
23
24     if ( sigaddset(&newset, SIGINT) < 0 )
25     {
26         perror("sigaddset\n");
27     }
28
29     if ( sigprocmask(SIG_BLOCK, &newset, &oldset) < 0 )
30     {
31         perror("sigprocmask\n");
32     }
33     printf("\nSIGINT block\n");
34
35     sleep(5);
36
37     if ( sigpending(&pendmask) < 0)
38     {
39         perror("sigpending\n");
40     }
41
42     if ( sigismember(&pendmask, SIGINT) )
43     {
44         printf("SIGINT is pendding\n");
45     }
46
47     if ( sigprocmask(SIG_SETMASK, &oldset, NULL) < 0 )
48     {
49         perror("sigprocmask\n");
50     }
51     printf("\nSIGINT unblock\n");
52
53     sleep(5);
54     return 0;
55 } 

  在进入第一次睡眠前,设置好了信号掩码,SIGINT将被阻塞,若在唤醒前按下ctrl+c(发送SIGINT),不会进行任何响应,事实上,如果不进行阻塞的话,收到任何信号将会唤醒sleep。等到第二次调用sigprocmask将signal mask恢复,则之前的那个SIGINT就会被响应,再次按下ctrl+c,int立马解除了第二个sleep。

运行结果:

SIGINT block
^C^C                       <----------此处阻塞了
SIGINT is pendding
catch SIGINT

SIGINT unblock
^C                         <------------此处立马响应

并且可以看到,第一次连续发了2个SIGINT但是下面只响应了一次,说明阻塞的信号并不会在一个阻塞队列里面。

时间: 2024-08-28 17:30:41

sigemptyset,sigfillset,sigaddset,sigdelset,sigismember,sigprocmask,sigpendmask作用的相关文章

信号处理篇alarm ferror kill mkfifo pause pclose perror pipe popen sigaction sigaddset sigdelset sigemptyset signal sleep strerror

alarm(设置信号传送闹钟) 相关函数 signal,sleep 表头文件 #include<unistd.h> 定义函数 unsigned int alarm(unsigned int seconds); 函数说明 alarm()用来设置信号SIGALRM在经过参数seconds指定的秒数后传送给目前的进程.如果参数seconds 为0,则之前设置的闹钟会被取消,并将剩下的时间返回. 返回值 返回之前闹钟的剩余秒数,如果之前未设闹钟则返回0. 范例 #include<unistd.h

linux 信号处理

前言 Linux中的信号是向进程异步发送的事件通知,通知进程有事件(硬件异常.程序执行异常.外部发出信号)发生.当信号产生时,内核向进程发送信号(在进程所在的进程表项的信号域设置对应于该信号的位).内核处理一个进程收到的信号的时机是在一个进程从内核态返回用户态时,当一个进程在内核态运行时,软中断信号并不立即起作用,要等到将返回用户态时才处理,进程只有处理完信号才会返回用户态,进程在用户态下不会有未处理完的信号.内核为每个进程维护一个(未处理)的信号队列,信号产生后首先被放入到未决队列中,如果进程

linux应用程序编程应该要学习的函数使用列表

linux应用程序编程应该要学习的函数使用列表 linux应用层编程相关的man page,具体包括的命令和函数,请参考https://www.kernel.org/doc/man-pages/ select().pselect().poll().epoll(), epoll_create(),epoll_wait(),epoll_ctl(),close()==同时监控多个fd的输入.输出 inotify机制,inotify_init(),inotify_add_watch(),inotify_

2信号处理之:信号产生原因,进程处理信号行为,信号集处理函数,PCB的信号集,sigprocmask()和sigpending(),信号捕捉设定,sigaction,C标准库信号处理函数,可重入函数,

 1信号产生原因 2.进程处理信号行为 manpage里信号3中处理方式: SIG_IGN SIG_DFL                                            默认Term动作 a signal handling function 进程处理信号 A默认处理动作 term   中断 core    core(调试的时候产生) gcc –g file.c ulimit –c 1024 gdb a.out core ign      忽略 stop     停止

sigsuspend sigprocmask函数的用法

一个进程的信号屏蔽字规定了当前堵塞而不能递送给该进程的信号集.调用函数sigprocmask能够检測或更改其信号屏蔽字,或者在一个步骤中同一时候运行这两个操作. #include <signal.h> int sigprocmask( int how, const sigset_t *restrict set, sigset_t *restrict oset ); 返回值:若成功则返回0,若出错则返回-1 首先,若oset是非空指针,那么进程的当前信号屏蔽字通过oset返回. 其次,若set是

sigsuspend sigprocmask函数的使用方法

一个进程的信号屏蔽字规定了当前阻塞而不能递送给该进程的信号集.调用函数sigprocmask可以检测或更改其信号屏蔽字,或者在一个步骤中同时执行这两个操作. #include <signal.h> int sigprocmask( int how, const sigset_t *restrict set, sigset_t *restrict oset ); 返回值:若成功则返回0,若出错则返回-1 首先,若oset是非空指针,那么进程的当前信号屏蔽字通过oset返回. 其次,若set是一个

linux_api之信号

本片索引: 1.引言 2.信号 3.程序启动 4.signal函数 5.系统调用的中断和系统调用的重启(了解) 6.可再入与不可再入函数(了解) 7.kill函数和raise函数 8.alarm函数和pause函数 9.信号的发送.接收和处理的过程 10.信号集设置函数和sigprocmask函数 11.sigpending函数 12.sigaction函数 13.sigsuspend函数 14.abort函数 15.sleep函数           1.引言 信号是一种软件中断,与之相对应的

Linux之信号第二谈

重提信号概念 前一篇中提到了信号的概念,并且对信号的产生及一些属性有了一定的认识,这一次,要从更加深入的角度看待信号. 之前提到过,当我的进程在接收到信号之前,就已经知道了,当我接收到某种信号之后就要发生某一项动作,换句话说,在进程内部,一定存在这某种结构,将这些信息都记录了下来,很明显,对于进程而言,这些信息都会保存在它的PCB当中. 首先我们来认识这样几个概念: 信号递达(Delivery):执行信号的处理动作: 信号未决(Pending):信号从产生到递达之间的状态: 阻塞(Block):

Linux系统开发6 信号

[本文谢绝转载,原文来自http://990487026.blog.51cto.com] <大纲> Linux系统开发6 信号 linux系统有64种信号 signal man文档 终端按键信号 ctrl +c SIGIN ctrl +z SIGTSTP ctrl +\ SIGQUIT 硬件产生信号 浮点数例外信号  访问非法内存 kill()函数 信号与权限 kill()函数的pid 与返回值 信号产生原因 raise() 信号 abort() 信号 alarm() 信号 收到信号的默认操作