信号的捕获和处理

      信号(signal)是在特定事件发生时由操作系统向进程发送的消息。它一种软件中断,是进程间唯一的异步通信方式。

      信号有很多,常见的有:

  • SIGINT:在键盘按下组合键后产生,默认动作为终止进程
  • SIGQUIT:在键盘按下组合键后产生,默认动作为终止进程
  • SIGKILL:无条件终止进程。本信号不能被忽略、处理和阻塞。默认动作为终止进程。它向系统管理员提供了一种可以杀死任何进程的方法
  • SIGALRM:定时器超时,超时的时间由系统调用alarm设置。默认动作为终止进程
  • SIGCHLD:子进程结束时,父进程会收到这个信号。默认动作为忽略该信号


      信号的捕捉和处理


      信号的捕捉和处理由以下2个函数来完成,其中第一个函数也是由第二个函数实现的:

#include 
sighandler_t signal(int signum, sighandler_t handler);
int sigaction(int signum, const struct sigaction *act, struct sigaction *oldact);

      参数signum指定信号的种类,比如SIGINT、SIGKILL等。

      参数handler是一个函数指针,指定捕捉到该信号后的处理函数。

      signal函数执行成功时返回信号处理函数指针,发生错误时返回SIG_ERR。

      sigaction函数类似于signal函数,而且它完全可以替代后者,也更稳定。之所以稳定,是signal函数在UNIX系列的不同操作系统中可能存在区别,但sigaction函数完全相同。实际上现在很少用signal函数来编写程序,它只是为了保持对旧程序的兼容。

1. signal()函数

#include 
#include 

/*信号处理函数*/
void handler_sigint(int signo)
{
	printf("recv SIGINT\n");
}

int main()
{
	/*安装信号处理函数*/
	signal(SIGINT, handler_sigint);
	
	while(1)
		;

	return 0;
}

      程序使用signal()安装SIGINT的处理函数handler_sigint,然后进入无限循环。当接收到SIGINT信号时,程序自动跳转到信号处理函数处执行,打印出提示信息。然后返回主函数继续无限循环。执行结果如下:

信号的捕获和处理_第1张图片


2. sigaction()函数

      sigaction函数中用到了一个结构体sigaction作为参数。此结构体中的字段常用的有2个,sa_handler用来指定信号发生后的处理函数,sa_flags用来进行一些设定。

#include 
#include 
#include 

int temp = 0;

/*信号处理函数*/
void handler_sigint(int signo)
{
	printf("recv SIGINT\n");
	sleep(5);
	temp += 1;
	printf("the value of temp is: %d\n", temp);
	printf("in handler_sigint, after sleep\n");
}

int main()
{
	struct sigaction act;
	
	/*赋值act结构*/
	act.sa_handler = handler_sigint;
	act.sa_flags = SA_NOMASK;      //此设置意味着,对于可靠信号,发生了多少次,就调用信号处理函数多少次,即信号不会丢失
	/*安装信号处理函数*/
	sigaction(SIGINT, &act, NULL);
	
	while(1)
		;

	return 0;
}

      运行上述程序后,在键盘上快速按下5次组合键,屏幕上会连续打印出5行提示消息。在休眠5秒后,再将临时变量temp的值依次打印出来。这是由于设定了sa_flags的值为SA_NOMASK,因此程序能够反复响应信号SIGINT,程序从sleep()处嵌套调用信号处理函数handler_sigint,多次打印出“recv SIGINT”。睡眠5秒后,将temp的值打印出来并返回到本次信号处理程序的跳入点sleep()处,最后返回到主函数。

信号的捕获和处理_第2张图片

你可能感兴趣的:(C)