Linux 对信号的总结
Linux信号_总结
对信号本质的理解:
类似于中断,区别在于中断是由硬件产生的,而信号是由软件实现的。
信号的来源:
触发硬件(触发键盘,或是硬件故障);软件信号函数kill 、alarm、setitimer、sigqueue 等函数。
SRE实战 互联网时代守护先锋,助力企业售后服务体系运筹帷幄!一键直达领取阿里云限量特价优惠。信号的分类:
可靠信号与不可靠信号,实时信号与非实时信号;
不可靠信号:
SIGRTMIN前的信号称为不可靠信号,在早期这段信号可能做出错误的反应,或是丢失。因此对此段信号成为不可靠信号。
可靠信号:
在SIGRTMIN与SIGRTMAX之间的信号称做可靠信号,可靠信号是为了防止信号丢失的。这些信号可以排队处理。
实时信号与非实时信号:
非实时信号都不支持排队,都是不可靠信号;实时信号都是支持排队的,都是可靠信号;
对信号的响应:
响应的三种方式
(1)忽略信号
有两个特殊的信号SIGKILL 和SIGSTOP信号不能被忽略。
(2)捕捉信号
给对应的信号绑定响应的处理函数,带到信号产生时,执行对应的函数。
(3)执行缺省信号
进程对实时信号的缺省反应时进程的终止。
信号的发送:
发送信号的函数有,kill(), alarm(),raise(),setitimer();
(1)kill(int pid, int signal);
PID参数 | 信号的就收进程 |
---|---|
pid>0 | 进程的ID为pid的进程 |
pid=0 | 同一个进程组 |
pid<0 && pid!=-1 | 进程组ID为pid绝对值的所有进程 |
pid=-1 | 发送至所有ID大于1的进程 |
参数介绍:
pid为进程号,singnal为信号值。
kill常用于pid>0的信号处理,调用成功返回0,否则返回-1。
(2)alarm(unsigned int seconds)
专门为SIGALRM信号而设函数,seconds表示时间,此函数意味着在seconds秒后向SIGALRM信号发送消息。
进程调用alarm后,以前的alarm()调用都将无效。若调用alarm()前,进程中已经设置了闹钟,则返回上一个闹钟生于的时间,否则返回0;
eg:
#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));
}
//运行结果为
first time return:0
after sleep(1),remain:3
renew alarm,remain:2
(3)raise(int signal);
此函数时向本进程发送signal信号的,signal为即将发送的信号值。调用成功返回0;否则返回 -1。
(4)setitimer()函数
int setitimer(int which, const struct itimerval *value, struct itimerval *ovalue));
结构体介绍:
struct itimerval
{
struct timeval it_interval;//间隔时间
struct timeval it_value; //初始时间
};
struct timeval
{
long tv_sec; //秒
long tv_usec; //微妙
};
参数描述:
which:表示定时器类型,setitimer有三种定时器类型。
ITIMER_REAL : 以系统真实的时间来计算,它送出SIGALRM信号。
ITIMER_VIRTUAL : 设定程序执行时间;经过指定的时间后,内核将发送SIGVTALRM信号给本进程;
ITIMER_PROF : 设定进程执行以及内核因本进程而消耗的时间和,经过指定的时间后,内核将发送ITIMER_VIRTUAL信号给本进程;
it_interval指定间隔时间,it_value指定初始定时时间。如果只指定it_value,就是实现一次定时;如果同时指定 it_interval,则超时后,系统会重新初始化it_value为it_interval,实现重复定时;
eg:
#include <signal.h>
#include <unistd.h>
#include <stdio.h>
#include <sys/time.h>
void sigroutine(int signo) {
switch (signo) {
case SIGALRM:
printf("Catch a signal -- SIGALRM\n");
break;
case SIGVTALRM:
printf("Catch a signal -- SIGVTALRM\n");
break;
}
}
int main(int argc, char ** argv) {
struct itimerval value,ovalue,value2;
printf("process id is %d\n",getpid());
signal(SIGALRM, sigroutine); //为SIGALRM信号绑定sigroutine函数
signal(SIGVTALRM, sigroutine); //为SIGVTALRM信号绑定sigroutine函数
value.it_value.tv_sec = 1;//设定起始时间
value.it_value.tv_usec = 0;
value.it_interval.tv_sec = 1;//设定终止时间
value.it_interval.tv_usec = 0;
setitimer(ITIMER_REAL, &value, &ovalue);
value2.it_value.tv_sec = 0;
value2.it_value.tv_usec = 500000;
value2.it_interval.tv_sec = 0;
value2.it_interval.tv_usec = 500000;
setitimer(ITIMER_VIRTUAL, &value2, &ovalue);
for (;;) ;
}
//运行结果为
process id is 3136
Catch a signal -- SIGVTALRM
Catch a signal -- SIGALRM
Catch a signal -- SIGVTALRM
Catch a signal -- SIGVTALRM
Catch a signal -- SIGALRM
Catch a signal -- SIGVTALRM
Catch a signal -- SIGVTALRM
Catch a signal -- SIGALRM
Catch a signal -- SIGVTALRM
Catch a signal -- SIGVTALRM
Catch a signal -- SIGALRM
Catch a signal -- SIGVTALRM
Catch a signal -- SIGVTALRM
Catch a signal -- SIGALRM
Catch a signal -- SIGVTALRM
Catch a signal -- SIGVTALRM
Catch a signal -- SIGALRM