【原创】《Linux高级程序设计》杨宗德著 - 进程管理与程序开发 - Linux常见信号及处理
Linux的信号是一种进程间一步通信的机制,在实现上是一种软中断,信号可以导致一个正在运行的进程被异步打断,转而处理一个突发事件。异步事件是不可预见的,只能通过某些特定的方式来预防,或者说,当异步事件发生时根据原来设定完成相应的操作。
Linux常见信号及处理,这里只列出几个:
信号的基本概念
安装信号、安装中断、递送信号、捕获信号、屏蔽信号、忽略信号、未决信号、可靠信号与不可靠信号。详见教材236页。
信号处理流程
(1)信号被某个进程产生,并设置此信号传递的对象(一般为对应进程的pid),然后传递给操作系统;
(2)操作系统根据接收进程的设置(是否阻塞)而选择性的发送给接收者,如果接收者阻塞该信号(且该信号是可以阻塞的),操作系统将暂时保留该信号,而不传递,直到该进程解除对此信号的阻塞(如果对应进程已经退出,则丢弃此信号);如果对应进程没有阻塞,操作系统将传递此信号;
(3)目的进程接收到此信号后,将根据当前进程对此信号设置的预处理方式,暂时终止当前代码的执行,保护上下文(主要包括临时寄存器数据、当前程序位置以及当前CPU的状态)、转而执行中断服务程序,执行完成后再恢复到被中断的位置。当然,对于可抢占式内核,在中断返回时还将引发新的调度。
可能的信号来源
--------发送信号---------
kill发送一个信号到进程
raise自举一个信号
alarm()定时
示例代码:
#include<signal.h>
#include<stdio.h>
int main(void)
{
printf("first time return:%d\n",alarm(4));
sleep(1);
printf("after sleep(1),remain:%d\n",alarm(2));
printf("renew alarm,remain:%d\n",alarm(1));
}
运行结果:
$ ./a.out
first time return:0
after sleep(1),remain:3
renew alarm,remain:2
ualarm()定时
示例代码:
#include<unistd.h>
#include<signal.h>
#include<errno.h>
#include<stdio.h>
void handler()
{
printf("int:hello\n");
}
int main()
{
int i;
signal(SIGALRM,handler);
printf("%d\n",ualarm(300000,100000));
//alarm(2);
while(1)
{
sleep(1);
printf("test\n");
}
}
运行结果:
0$ ./a.out
0
int:hello
test
int:hello
test
int:hello
test
int:hello
test
下面省略。。。。。。
setitimer定时器应用
示例代码:
#include <stdio.h>
#include <stdlib.h>
#include <sys/time.h>
#include <signal.h>
int main(void)
{
struct itimerval setvalue;
setvalue.it_interval.tv_sec=3;
setvalue.it_interval.tv_usec=0;
setvalue.it_value.tv_sec=3;
setvalue.it_value.tv_usec=0;
setitimer(ITIMER_REAL,&setvalue,NULL);
setvalue.it_interval.tv_sec=3;
setvalue.it_interval.tv_usec=0;
setvalue.it_value.tv_sec=3;
setvalue.it_value.tv_usec=0;
setitimer(ITIMER_VIRTUAL,&setvalue,NULL);
setvalue.it_interval.tv_sec=3;
setvalue.it_interval.tv_usec=0;
setvalue.it_value.tv_sec=1;
setvalue.it_value.tv_usec=0;
setitimer(ITIMER_PROF,&setvalue,NULL);
while(1)
{
struct itimerval value;
getitimer(ITIMER_REAL,&value);
printf("ITIMER_REAL: internal:%ds%dms,remain:%ds%dms
\n",value.it_interval.tv_sec,value.it_interval.tv_usec,value.it_value.tv_sec,value.it_valu
e.tv_usec);
getitimer(ITIMER_VIRTUAL,&value);
printf("ITIMER_VIRTUAL:internal:%ds%dms,remain:%ds%dms
\n",value.it_interval.tv_sec,value.it_interval.tv_usec,value.it_value.tv_sec,value.it_valu
e.tv_usec);
getitimer(ITIMER_PROF,&value);
printf("ITIMER_PROF: internal:%ds%dms,remain:%ds%dms\n
\n",value.it_interval.tv_sec,value.it_interval.tv_usec,value.it_value.tv_sec,value.it_valu
e.tv_usec);
sleep(1);
}
}
运行结果:
$ ./a.out
ITIMER_REAL: internal:3s0ms,remain:2s999363ms
ITIMER_VIRTUAL:internal:3s187ms,remain:3s4187ms
ITIMER_PROF: internal:3s187ms,remain:1s62ms
ITIMER_REAL: internal:3s0ms,remain:1s998221ms
ITIMER_VIRTUAL:internal:3s187ms,remain:3s4187ms
ITIMER_PROF: internal:3s187ms,remain:1s62ms
ITIMER_REAL: internal:3s0ms,remain:0s997588ms
ITIMER_VIRTUAL:internal:3s187ms,remain:3s4187ms
ITIMER_PROF: internal:3s187ms,remain:1s62ms
闹钟
注意:
SIGSTOP和SIGKILL这两个信号不能被屏蔽和安装,也就是说,用户不能自定义这两个信号的处理方式。