【原创】《Linux高级程序设计》杨宗德著 - 进程管理与程序开发 - Linux常见信号及处理

时间:2022-07-11 10:24:40


【原创】《Linux高级程序设计》杨宗德著 - 进程管理与程序开发 - Linux常见信号及处理


Linux的信号是一种进程间一步通信的机制,在实现上是一种软中断,信号可以导致一个正在运行的进程被异步打断,转而处理一个突发事件。异步事件是不可预见的,只能通过某些特定的方式来预防,或者说,当异步事件发生时根据原来设定完成相应的操作。

Linux常见信号及处理,这里只列出几个:

【原创】《Linux高级程序设计》杨宗德著 - 进程管理与程序开发 - Linux常见信号及处理

信号的基本概念

安装信号、安装中断、递送信号、捕获信号、屏蔽信号、忽略信号、未决信号、可靠信号与不可靠信号。详见教材236页。

信号处理流程

(1)信号被某个进程产生,并设置此信号传递的对象(一般为对应进程的pid),然后传递给操作系统;
(2)操作系统根据接收进程的设置(是否阻塞)而选择性的发送给接收者,如果接收者阻塞该信号(且该信号是可以阻塞的),操作系统将暂时保留该信号,而不传递,直到该进程解除对此信号的阻塞(如果对应进程已经退出,则丢弃此信号);如果对应进程没有阻塞,操作系统将传递此信号;
(3)目的进程接收到此信号后,将根据当前进程对此信号设置的预处理方式,暂时终止当前代码的执行,保护上下文(主要包括临时寄存器数据、当前程序位置以及当前CPU的状态)、转而执行中断服务程序,执行完成后再恢复到被中断的位置。当然,对于可抢占式内核,在中断返回时还将引发新的调度。

可能的信号来源

【原创】《Linux高级程序设计》杨宗德著 - 进程管理与程序开发 - Linux常见信号及处理

--------发送信号---------

kill发送一个信号到进程

【原创】《Linux高级程序设计》杨宗德著 - 进程管理与程序开发 - Linux常见信号及处理

raise自举一个信号

【原创】《Linux高级程序设计》杨宗德著 - 进程管理与程序开发 - Linux常见信号及处理

alarm()定时

【原创】《Linux高级程序设计》杨宗德著 - 进程管理与程序开发 - Linux常见信号及处理

示例代码:

#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()定时

【原创】《Linux高级程序设计》杨宗德著 - 进程管理与程序开发 - Linux常见信号及处理

示例代码:

#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这两个信号不能被屏蔽和安装,也就是说,用户不能自定义这两个信号的处理方式。


原文链接:http://blog.csdn.net/geng823/article/details/40919047