测测你的Linux如何处理信号量?

在你的Linux系统中,一个进程是如何响应多个信号的?

做个小实验~上代码。

 
#include<stdio.h>
#include<signal.h>

#define INPUTLEN  (100)

int main(int ac, char* av[])
{
	void inthandler(int);
	void quithandler(int);
	char input[INPUTLEN];
	int  nchars;
	
	signal(SIGINT, inthandler);
	signal(SIGQUIT, quithandler);

	do{
		printf("\nType a message\n"); 
		nchars = read(0, input, (INPUTLEN-1));
		if(nchars == -1)
		    perror("read returned an error");
		else
		{
			input[nchars] = '\0';
			printf("You typed: %s", input);
		}
	}while(strncmp(input, "quit", 4) != 0);
}

void inthandler(int s)
{
	printf("Received signal %d.. waiting\n", s);
	sleep(2);
	printf("Leaving inthandler\n");
}

void quithandler(int s)
{
	printf("Received signal %d .. waiting \n", s);
	sleep(3);
	printf("Leaving quithandler\n");
}

     流程很简单,为SIGINT,SIGQUIT设定信号处理函数,主程序一直循环,接收来自stdin的输入,直到接收到"quit"结束。

     SIGINT 信号,可以由ctrl+c 来产生,SIGQUIT信号,可以由 ctrl+\ 来产生。编译之后,来看现象。

1、SIGINT+SIGINT+SIGINT+SIGINT(多个相同信号)

    笔者的系统是ubuntu9.10,连续发送4个SIGINT后,系统先处理一个,再阻塞一个,忽略后两个。处理完第一个后,阻塞的才被处理。SIGQUIT同样效果。

    如果两个SIGINT就杀死了进程,那么意味着你的系统是不可靠的信号: 处理函数必须每次都重置。如果多个SIGINT信号没有杀死进程,意味着处理函数在被调用后还起到作用。后者对重复信号的处理,一般有三个选择:

    (1).递归,调用同一个处理函数。(非显式递归,虽然处理函数没有调用自己,但是效果相同,如果设置一个静态变量在这里,效果就更明显了~~)

    (2).忽略第二个。

    (3).阻塞第二个信号直到第一个处理完毕。

     当然了,你的Linux很可能会将多个信号进行入队操作,一个接一个处理完毕,或者有限地抛弃。

2、SIGINT+SIGQUIT+SIGINT+SIGQUIT(不同信号交替)

    这里同样处理一个,阻塞一个,忽略后两个。当先后发送SIGINT 和SIGQUIT后,会看到程序先跳到inthandler, 接着跳到quithandler。然后再回到inthandler,最后回到主循环。

3、在处理信号的时候,输入字符。

    很幸运,在信号处理完毕返回主程序的时候,所于的输入都正确处理并返回了。


从这个小实验中,我们会发现使用signal(),来设定信号量的处理方式过于被动,而且简陋。首先,我们无法获知中断信号的来源。这样导致我们设定信号处理函数的时候能预防的情况过少。其次,多个信号的处理方式无法亲手设定,阻塞还是抛弃?如果要处理,阻塞多少个?还有,在信号处理返回的时候,已经执行的函数,或者系统调用,是重新开始,还是继续进行?对于一些不可重入函数,这一点就非常关键。能自由定制信号量,很有必要的。





评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值