我是靠谱客的博主 奋斗乐曲,最近开发中收集的这篇文章主要介绍signal 和 sigaction 函数,觉得挺不错的,现在分享给大家,希望可以做个参考。

概述

一、signal函数

signal()函数只处理一次信号;
signal函数每次设置具体的信号处理函数只能生效一次, 每次在进程响应处理信号的时候,随即将信号处理函数恢复到默认方式;如果想多次以相同的方式处理某个信号,通常的做法是,在响应函数开始,再次设置signal;
但是依旧会有问题。在信号发出时候到信号处理程序中重新调用signal函数,存在一段时间。如果这段时间内接收到一个信号(此时还没有调用signal函数), 这个信号的处理方式依旧是默认的。

int sigint_handler(int sig)
{
	signal(SIGINT, sigint_handler);
	...
}

看一个例子,此函数只能处理一次信号

void sigint_handler(int signo)
{
	printf("ninterruptn");	//注意printf是不可重入函数;
}

int main()
{
	signal(SIGINT, sigint_handler);
	while(1){
		sleep(1);
		printf("mainn");
	}
	exit(0);
}

二、使用sigaction函数,实现一次函数调用处理多次信号

下面代码使用sigaction实现对多次信号的处理

int sigint_handler(int signo)
{
	printf("ninterruptn");
}

int main()
{
	struct sigaction action;
	action.sa_handler = sigint_handler;
	sigaction(SIGINT, &action, NULL);
	while(1){
		sleep(1);
		printf("mainn");
	}
	exit(0);
}

三、signal函数与系统调用

当进程在系统调用中阻塞着的话,使用signal函数进入信号处理程序时候,从信号处理程序返回时候,原先的系统调用会被失效。
对于下面代码,当在键盘键入Ctrl + C,进程会终止。这是由于在死循环中, 进程阻塞在fgets函数中的read系统调用上,当从信号处理程序返回的时候,read系统调用失败返回,退出死循环,进程于是终止。

void sigint_handler(int signo)
{
	printf("interruptn");
}

int main()
{
	signal(SIGINT, sigint_handler);
	void *ret;
	char buf[MAXLINE];
	while((ret = fgets(buf, MAXLINE, stdin)) != NULL){
		printf("results:%sn", buf);
		sleep(3);
	}
	exit(0);
} 

注意,当进程在sleep(3) 睡眠时候,此时终端有输入,这个输入会进入缓存排队,在进程结束睡眠之后,进程的fgets函数会从缓存的输入队列中读出;
可以考虑使用sigaction函数,设置action.sa_flags = SA_RESTART; 此时系统调用变成可重启;
代码如下:

void sigint_handler(int signo)
{
	printf("interruptn");
}

int main()
{
	void *ret;
	char buf[MAXLINE];
	struct sigaction action;
	action.sa_handler = sigint_handler;
	action.sa_flags = SA_RESTART;
	sigaction(SIGINT, &action, NULL);
	while((ret = fgets(buf, MAXLINE, stdin)) != NULL){
		printf("results:%sn", buf);
		sleep(3);
	}
	printf("fgets errorn");
	exit(0);

最后

以上就是奋斗乐曲为你收集整理的signal 和 sigaction 函数的全部内容,希望文章能够帮你解决signal 和 sigaction 函数所遇到的程序开发问题。

如果觉得靠谱客网站的内容还不错,欢迎将靠谱客网站推荐给程序员好友。

本图文内容来源于网友提供,作为学习参考使用,或来自网络收集整理,版权属于原作者所有。
点赞(39)

评论列表共有 0 条评论

立即
投稿
返回
顶部