- int sigemptyset(sigset_t *set);
- int sigfillset(sigset_t *set);
- int sigaddset(sigset_t *set,int setnum);
- int sigdelset(sigset_t *set,int setnum);
set表示信号集指针,setnum表示信号。
sigemptyset 用于将set指向的信号集设为空,即不包含任何信号。
sigfillset 用于将set指向的信号集设为满,即包含所有的信号。
sigaddset 用于向信号集中添加信号。即向set指向的信号集中添加signum信号量
sigdelset 用于向信号集中删除信号。即向set指向的信号集中删除signum信号量
以上函数成功返回0,失败返回-1 。
int sigismember(const sigset_t *set,int signum)
用于检测signumber是否在set中,若属于返回1,不是返回0,出错返回-1.
二、信号屏蔽字
每个进程都会有一个信号屏蔽字,它规定了当前进程要阻塞的信号集。对于每种可能的信号,信号屏蔽字中都会有一位与之对应,如果该位被设置,也就是说明该信号被屏蔽了,则该信号当前就是阻塞的。
所谓屏蔽, 并不是禁止递送信号, 而是暂时阻塞信号的递送, 解除屏蔽后, 信号将被递送, 不会丢失. 进程可以通过sigprocmask()来获得和修改当前进程的信号屏蔽字。
int sigprocmask(int how, const sigset_t *restrict set, sigset_t *restrict oldset);
功能:可以用来检测或改变目前的信号屏蔽字
参数:
how:指示如何修改屏蔽信号
SIG_BLOCK 该进程新的信号屏蔽字是其当前信号屏蔽字和set指向信号集的并集。即将set所指向的信号集和当前的信号集屏蔽字按位或。set包含了我们希望阻塞的附加信号。
SIG_UNBLOCK 该进程新的信号屏蔽字是其当前信号屏蔽字和set所指向信号集的补集的交集。set包含了我们希望解除阻塞的信号.
SIG_SETMASK 该进程新的信号屏蔽字是set指向的值
oldset:是一个非空指针时,存放当前屏蔽信号集
set:是一个非空指针时,根据how修改屏蔽信号
如果set是个空指针,则不改变该进程的信号屏蔽字,how的值也无意义。
返回值:执行成功返回0,失败返回-1。
注:如果在调用sigprocmask之后有任何未决的,不再阻塞的信号,则在sigprocmask返回之前,至少会将其中一个信号递送给该进程。如:以前被屏蔽的信号,调用sigprocmask解除屏蔽,但在函数返回之前,该信号便会递送给进程,执行动作,之后函数才会返回。
int sigpending(sigset_t * set);
功能:返回当前未决的信号集(包括被阻塞不能递送而导致未决的信号)
参数:set:存放返回信号集
返回值:函数调用成功返回0,否则返回-1;
int sigaction(int signum,const struct sigaction *act ,struct sigaction *oldact);
功能:查询或设置信号处理方式(可同时两种操作)
参数:
signum:要操作的信号编号,可直接写信号的名字
act:若act指针非空,则要修改其动作
oldact : oldact 指针为空,则系统返回该信号的原先动作,并存在oldact中
}参数结构sigaction定义如下struct sigaction {void (*sa_handler)(int);void (*sa_sigaction)(int, siginfo_t *, void *);sigset_t sa_mask;int sa_flags;void (*sa_restorer)(void);
sa_handler:此参数和signal()的参数handler相同,代表新的信号处理函数,其他意义请参考signal()。信号处理函数可以采用void (*sa_handler)(int)或void (*sa_sigaction)(int, siginfo_t *, void *)。到底采用哪个要看sa_flags中是否设置了SA_SIGINFO位,如果设置了就采用void (*sa_sigaction)(int, siginfo_t *, void *),此时可以向处理函数发送附加信息;默认情况下采用void (*sa_handler)(int),此时只能向处理函数发送信号的数值。
返回值:成功返回0,出错:-1sa_mask:字段说明了一个信号集,在调用该信号捕捉函数之前,这一信号集要加到进程的信号屏蔽字中。仅当从信号捕捉函数返回时再将进程的信号屏蔽字复位为原先值。sa_flags :用来设置信号处理的其他相关操作,下列的数值可用。SA_RESTART:如果信号中断了进程的某个系统调用,则系统自动启动该系统调用SA_SIGINFO:如果设置了此标志,信号处理函数就采用void (*sa_sigaction)(int, siginfo_t *, void *),如果没有设置此标志,信号处理函数就采用void (*sa_handler)(int);SA_INTERRUPT:由此信号中断的系统调用不会自动启动(其它标记见UNIX环境高级编程)void (*sa_sigaction)(int, siginfo_t *, void *);其中siginfo_t结构体中包含了大量的信号携带信息,可以看出,这个函数比sa_handler要强大,因为前者只能传递一个信号代码,而后者可以传递siginfo_t信息。typedef struct siginfo_t{
int si_signo;//信号编号
int si_errno;//如果为非零值则错误代码与之关联
int si_code;//说明进程如何接收信号以及从何处收到
pid_t si_pid;//适用于SIGCHLD,代表被终止进程的PID
pid_t si_uid;//适用于SIGCHLD,代表被终止进程所拥有进程的UID
int si_status;//适用于SIGCHLD,代表被终止进程的状态
clock_t si_utime;//适用于SIGCHLD,代表被终止进程所消耗的用户时间
clock_t si_stime;//适用于SIGCHLD,代表被终止进程所消耗系统的时间
sigval_t si_value;
int si_int;
void * si_ptr;
void* si_addr;
int si_band;
int si_fd;
};
- 注:而对于sigaction(),Linux默认并不会自动重启动,所以如果希望执行信号处理后自动重启动先前中断的系统调用,就需要为sa_flags指定SA_RESTART标志
int main()
{
sigset_t sigset;
sigfillset(&sigset);/*填充所有信号*/
if(sigismember(&sigset,SIGINT))/*判断SIGINT*/
printf("SIGINT exist in signal_set!\n");
if(sigismember(&sigset,SIGTERM))
printf("SIGTERM exist in signal_set!\n");
if(sigismember(&sigset,SIGABRT))
printf("SIGABRT exist in signal_set!\n");
if(sigdelset(&sigset,SIGINT)<0)/*移除SIGINT*/
perror("del error\n");
else
printf("SIGINT have been removed!\n");
if(sigismember(&sigset,SIGINT))/*再次判断*/
printf("SIGINT exist in signal_set!\n");
else
printf("SIGINT not exist in signal_set!\n");
}