sigaction()函数:
#include <signal.h>
int sigaction(int signum, const struct sigaction *act, structsigaction *oldact);
各参数意义:
signum:信号值
act:包含处理信息的结构体
structsigaction {
void (*sa_handler)(int);
void (*sa_sigaction)(int, siginfo_t *, void *);
sigset_t sa_mask;
int sa_flags;
void (*sa_restorer)(void);
};
其中sa_handlersa_sigaction是互斥的属性,只能使用其中一种处理函数,sa_flags=0表示使用sa_handler
sa_mask表示在执行当前信号处理函数的时候,需要屏蔽的信号,进城最终屏蔽的信号位mask=mask|sa_mask,捕捉函数执行完成后,该sa_mask就失效了
——正在执行handler的时候,内核会自动将当前信号的屏蔽字设为1,如果有相同的信号进来,就会被忽略,当该信号被处理完成之后,内核又会将该信号阻塞位置0
eg:
函数实现使用sigaction()函数处理信号。
在处理信号的函数中,动态的获取当前进程的未决集,并打印输出
#include<stdio.h> #include<unistd.h> #include<signal.h>
voidsig_handler(int signum){ inti=5; sigset_tp; printf("Iam sig_handler\n"); while(i--){ intj; sigpending(&p);//获取未决集 for(j=1;j<31;j++){ if(sigismember(&p,j)==1){//判断未决集中的每一位 putchar('1'); }else{ putchar('0'); } } puts(""); printf("signum=%d\n",signum); sleep(1); } }
intmain(void){
structsigaction act; act.sa_handler=sig_handler; act.sa_flags=0; sigemptyset(&act.sa_mask);
//注册信号 sigaction(SIGINT,&act,NULL);
while(1){
printf("***************\n"); sleep(1); } return0; } ~ |
打印结果:
^CIam sig_handler //这里第一次执行ctrl+c命令发现调用了handler以后,未决集中的所有位都是0 000000000000000000000000000000 signum=2 ^C010000000000000000000000000000//在没有循环完成的时候,也就是handler没有执行完成的时候,再执行一次ctrl+c命令,这时候block实际上是阻塞的,又sa_mask设置,发现未决集的第二位也就是SIGINT对应的位置1了,但是由于当前block阻塞,所以未决集并不能发生变化 signum=2 010000000000000000000000000000 signum=2 010000000000000000000000000000 signum=2 010000000000000000000000000000 signum=2 //设置的循环时间结束,也就是handler执行结束之后,2号(SIGOINT)阻塞位恢复为0,,这时候发现未决集有未处理的信号,所以又再一次调用处理函数 Iam sig_handler 000000000000000000000000000000 signum=2 000000000000000000000000000000 signum=2 000000000000000000000000000000 signum=2 000000000000000000000000000000 signum=2 000000000000000000000000000000 signum=2 *************** |
小结:
1.未决集在调用handler的时候就又内核翻转了,不管handler是否已经完成
2.sigaction的结构体里面的sa_mask可以临时设置阻塞位,辅助handler完成信号处理
3.在处理信号过程中,由于未决集垓信号在处理的时候已经置0,所以还可以接手一次信号,但是该信号是否能别立刻处理,还是要看阻塞集对应位是否阻塞,如果阻塞,未决集就不再接收该信号,这也就是未决集是不支持排队的