屏蔽信号:
在 sigaction 的使用中,我们已经看到了表示信号集的 sigset_t 型数据。在 Linux 上有一组函
数专门用于对信号集进行操作:
#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);
set 参数指向要操作的信号集,而 signum 参数则代表一个指定的信号,各个函数的作用如下:
◆ sigemptyset:清空信号集,返回 0 表示成功,-1 表示失败;
◆ sigfillset:将所有信号加入信号集,返回 0 表示成功,-1 表示失败;
◆ sigaddset:将指定信号加入信号集,返回 0 表示成功,-1 表示失败;
◆ sigdelset:将指定信号从信号集中去除,返回 0 表示成功,-1 表示失败;
◆ sigismember:判断一个指定的信号是否在信号集中,返回 1 表示在信号集中,0 表示不在信
号集中,-1 表示有错误发生。
信号集在使用前需要先用 sigemptyset 或 sigfillset 函数进行初始化,然后用 sigaddset 或
sigdelset 函数增加或去除需要的信号。
在代码中也可以直接设置或获取进程的信号掩码:
int sigprocmask(int how, const sigset_t *set, sigset_t *oldset);
◆ how:指定操作信号掩码的方式。
◆ set:指向用于设置信号掩码的信号集。
◆ oldset:用于返回原来的信号掩码。
◆ 返回值:0 表示成功,-1 表示失败。
sigprocmask 函数将根据参数 how 指定的方式,设置当前进程的信号掩码,并把原来的信号掩码
保存在参数 oldset 指向的信号集中返回。如果 set 参数为 NULL,则不修改信号掩码;如果 oldset 参数
为 NULL,则不返回原来的信号掩码。how 有以下三个取值:
◆ SIG_BLOCK:将 set 参数指向信号集中的信号加入到信号掩码中。
◆ SIG_UNBLOCK:将 set 参数指向的信号集中的信号从信号掩码中删除。
◆ SIG_SETMASK:将 set 参数指向信号集设置为信号掩码。
因此,屏蔽某个信号可以有两种方式,下面以 SIGUSR1 信号为例进行说明:
第一种方式为使用 SIG_BLOCK 操作方式,代码如下:
sigset_t sigset;
sigemptyset(&sigset);
sigaddset(&sigset, SIGUSR1);
sigprocmask(SIG_BLOCK, &sigset, NULL);
第二种方式为使用 SIG_SETMASK 操作方式,代码如下:
sigset_t set;
sigprocmask(SIG_SETMASK, NULL, &set); //先得到当前的信号掩码
sigaddset(&set, SIGUSR1); //将要屏蔽的信号加入
sigprocmask(SIG_SETMASK, &set, NULL);
同时,要解除对信号的屏蔽,也有两种方式,仍以 SIGUSR1 信号为例:
第一种方式,使用 SIG_UNBLOCK 操作方式:
sigset_t sigset;
sigemptyset(&sigset);
sigaddset(&sigset, SIGUSR1);
sigprocmask(SIG_UNBLOCK, &sigset, NULL);
第二种方式,使用 SIG_SETMASK 操作方式:
sigset_t set;
sigprocmask(SIG_SETMASK, NULL, &set); //先得到当前的信号掩码
sigdelset(&set, SIGUSR1); //将要解除屏蔽的信号去除
sigprocmask(SIG_SETMASK, &set, NULL);
信号安全函数:
如前所述,进程在收到信号并对其进行处理时,会中断当前正在执行的指令序列,而去执行信号处
理函数。但是信号的传递是异步的,系统无法确定何时传递信号给进程。如果进程在收到信号时正在执行某
个不可重入的函数,这时捕捉到信号,进程就会转而去执行信号处理函数。如果在这个信号处理函数中又再
次调用了同一个函数,就有可能产生问题。
因此有些函数时不能在信号处理函数中调用的,那些可以在信号处理函数中调用且不会有潜在问题
的函数称为对信号安全的。下表列出了 Linux 系统中的信号安全函数,对于不在这个表中的函数,如果要
在信号处理函数中调用,则需谨慎处理。