一. 几个时刻点:
1.信号诞生;
2.信号在进程中注册完毕;
3.信号在进程中的注销完毕;
(信号加入进程屏蔽字block中,函数执行完毕返回时,block恢复为原来的值)
(不管是否屏蔽信号,注销是肯定的)
4.信号处理函数开始执行。
(sa_flags不为SA_NOMASK/SA_NODIFFER,该信号在此过程被屏蔽;否则不被屏蔽,可以执行。)
5.信号处理函数执行完毕。相邻两个事件的时间间隔构成信号生命周期的一个阶段。
二. 安装信号用signal和sigaction函数
signal用于安装不可靠信号
sigaction可以安装可靠和不可靠信号
1. 函数:int sigaction(ing signum, const struct sigaction *act, struct struct sigaction *oldact);中
函数执行成功返回0,执行失败返回-1,错误码仿如errno中。
signum是信号编号;
act和oldact都是sigaction类型的结构体
2.sigaction类型结构体
struct sigaction
{
void (*sa_handler)(int); 处理函数
void (*sa_sigaction)(int, siginfo_t *, void *); 处理函数(二者选其一)(第二个参数为结构体指针,指定要传送给函数数据,第一个为信号编号,第三个一般为NULL)
sigset_t sa_mask; 屏蔽字,指定block中要屏蔽的信号,缺省为当前处理的信号(sa_flags不指定为SA_NOMASK)
int sa_flags; 标志字。
void (*sa_restorer)(void); 现在已经不用了
}
sa_flags设置为SA_SIGINFO,则使用第二个处理函数。
struct siginfo
{
所有信号都有这三个数据成员
int si_signo;信号编号
int si_errno;错误码
int si_code;信号产生的原因
...
}
三. 看以下程序:
#include<stdio.h>
#include<setjmp.h>
#include<signal.h>
#include<unistd.h>
#define ENV_UNSAVE 0
#define ENV_SAVED 1
int flag_saveenv=ENV_UNSAVE;
jmp_buf env;
void handler_sigrtmin15(int signo)
{
if(flag_saveenv==ENV_UNSAVE)
return;
printf("recv SIGRTMIN+15\n");
sleep(5);
printf("in handler_sigrtmin15,after sleep\n");
siglongjmp(env,1);
}
int main()
{
// sleep(5);
switch(sigsetjmp(env,1))
{
case 0:
printf("return 0\n");
// flag_saveenv=ENV_SAVED;
break;
case 1:
printf("return from SIGRTMIN+15\n");
break;
default:
printf("return else\n");
break;
}
signal(SIGINT,handler_sigrtmin15);
printf("gotowhile\n");
while(1)
;
return 0;
}
信号处理函数中return到了while循环里,而不是signal函数中。
以下程序也是这样:
#include<stdio.h>
#include<unistd.h>
#include<signal.h>
int temp=0;
void handler_sigint(int signo)
{
printf("\nrecv SIGINT\n");
sleep(4);
temp+=1;
printf("the value of temp is %d\n",temp);
printf("in handler_sight,after sleep\n");
}
int main()
{
struct sigaction act;
act.sa_handler=handler_sigint;
act.sa_flags=SA_NOMASK;
sigaction(SIGINT,&act,NULL);
while(1)
;
return 0;
}
在信号处理函数的sleep期间第二次按下ctrl C,响应完成后返回到sleep函数处,然后立刻执行下面的语句,不再sleep。而不是返回到sigaction函数处。因此,signal和sigaction只是安装了响应函数,而不是调用。可以认为是在信号发生处调用了信号处理函数,如果运行完或return,就返回到信号发生处。
四. 为给SIGINT安装响应函数时,按ctrl C默认的是终止进程;如果安装后,就按照响应函数去执行。
五. 信号处理函数执行到siglongjmp(env,1)时,siglongjmp先去除当前的信号屏蔽字,然后准备返回,但是若是去除当前屏蔽字之后,未决信号队列仍然有信号,那么返回前,先响应信号。
信号响应函数执行完时,block才会回复原来值。