信号处理(一)
在Linux下当我们想强制结束一个程序的时候,我们通常会给它发送一个信号然后该进程捕捉到信号,再然后该进程执行一定操作最
终被终止.信号是UNIX和Linux系统响应某些条件而产生的一个事件,接收到该信号的进程会相应地采取一些行动。通常信号是由一
个错误产生的。但它们还可以作为进程间通信或修改行为的一种方式,明确地由一个进程发送给另一个进程。一个信号的产生叫生
成,接收到一个信号叫捕获。信号的捕捉这篇可能不会详细的说到,因为我想给它专门讲一个博客,因为信号捕捉的实例也是蛮多的.
首先我们认识一下这些信号:
1) SIGHUP 2) SIGINT 3) SIGQUIT 4) SIGILL
5) SIGTRAP 6) SIGABRT 7) SIGBUS 8) SIGFPE
9) SIGKILL 10) SIGUSR1 11) SIGSEGV 12) SIGUSR2
13) SIGPIPE 14) SIGALRM 15) SIGTERM 17) SIGCHLD
18) SIGCONT 19) SIGSTOP 20) SIGTSTP 21) SIGTTIN
22) SIGTTOU 23) SIGURG 24) SIGXCPU 25) SIGXFSZ
26) SIGVTALRM 27) SIGPROF 28) SIGWINCH 29) SIGIO
30) SIGPWR 31) SIGSYS 34) SIGRTMIN 35) SIGRTMIN+1
36) SIGRTMIN+2 37) SIGRTMIN+3 38) SIGRTMIN+4 39) SIGRTMIN+5
40) SIGRTMIN+6 41) SIGRTMIN+7 42) SIGRTMIN+8 43) SIGRTMIN+9
44) SIGRTMIN+10 45) SIGRTMIN+11 46) SIGRTMIN+12 47) SIGRTMIN+13
48) SIGRTMIN+14 49) SIGRTMIN+15 50) SIGRTMAX-14 51) SIGRTMAX-13
52) SIGRTMAX-12 53) SIGRTMAX-11 54) SIGRTMAX-10 55) SIGRTMAX-9
56) SIGRTMAX-8 57) SIGRTMAX-7 58) SIGRTMAX-6 59) SIGRTMAX-5
60) SIGRTMAX-4 61) SIGRTMAX-3 62) SIGRTMAX-2 63) SIGRTMAX-1
64) SIGRTMAX
列表中,编号为1 ~ 31的信号为传统UNIX支持的信号,是不可靠信号(非实时的),编号为32 ~ 63的信号是后来扩充的,称做可靠
信号(实时信号)。不可靠信号和可靠信号的区别在于前者不支持排队,可能会造成信号丢失,而后者不会。我们这些新手就着重
究前31个,后面的对于现在来说用处不大.
信号的产生:
产生信号的条件主要有:
1.用户在终端按下某些建时,终端驱动程序会发送信号给前台进程,例如ctrl -c 产生SIGINT信号.ctrl-\产生SIGQUIT信号,
Ctrl-Z产生SIGTSTP信号(可使前台进程停止)
2.硬件异常产生信号,这些条件由硬件检测到并通知内核,然后内核向当前进程发送适当的信号.例如当前进程执行了除以0的
指令,CPU的运算单元会产生异常,内核将这个异常解释为SIGFPE信号发送给进程.在比如当前进程访问了非法内存地址,MMU会
产生异常,内核将这个异常解释为SIGSEGV信号发送给进程.
3,一个进程调用kill(2)函数可以发送信号到另一个进程.可以用kill(1)命令发送信号给某个进程,kill(1)命令也是调用kill
(2)函数实现的,如果不明确指定信号则发送SIGTERM信号,该信号的默认处理是终止进程.当内核检测到某种软件条件发生时也
可以通过信号通知进程. 例如闹钟超时产生SIGALRM信号,向读端已关闭的管道写数据时产生SIGPIPE信号.如果不想按默认动作
处理信号,用户程序可以调用sigacttion(2)函数告诉内核处理某种信号.
再然后,你接收到信号的处理动作有一下三种:
1.忽略此信号
2.执行该信号的默认处理动作
3.提供一个信号处理函数,要求内核处理该信号时切换到用户执行这个处理函数,这种方式称为捕捉一个信号.
信号的阻塞
主要信号的函数:
例题:
#include<stdio.h>#include<signal.h>
#include<unistd.h>
void printsigset(sigset_t *set)
{
int i = 0;
for(;i<32;i++){
if(sigismember(set,i))
putchar('1');
else
putchar('0');
}
puts("");
}
int main()
{
sigset_t s,p;
sigemptyset(&s);
sigaddset(&s,SIGINT);
sigprocmask(SIG_BLOCK,&s,NULL);
while(1)
{
sigpending(&p);
printsigset(&p);
sleep(1);
}
return 0;
}
我们加上注释:
这个程序的大概意思就是 我们阻塞一个信号集,让它一直处于未决状态,并把它里面的信号编号显示出来,比如中途我们加入了一
个ctrl+c,后面信号集里面就会出现这个信号,然后他们还是一直处于未决状态.
特别提醒:如果一个信号被进程阻塞,它就不会传递给进程,但会停留在待处理状态,当进程解除对待
处理信号的阻塞时,待处理信号就会立刻被处理。