【原创】《Linux高级程序设计》杨宗德著 - 进程管理与程序开发 - 信号集与屏蔽信号 分类: Linux --- 应用程序设计 2014-11-08 13:19 53人阅读 评论(0) 收藏


【原创】《Linux高级程序设计》杨宗德著 - 进程管理与程序开发 - 信号集与屏蔽信号


中断是可以被屏蔽(阻塞)的(部分硬件中断是必须立即处理的,例如复位中断),因此,Linux的信号是可以屏蔽,即阻塞信号。但这与前面提到的忽略是有区别的。

信号忽略:系统仍然传递该信号,只是相应进程对该信号不作任何处理而已。
信号阻塞:系统不传递该信号,显示该进程无法接收到该信号直到进程的信号集发生改变。

sigprocmask设置进程屏蔽信号集

获取当前未决的信号

任何已经发送给进程,而没有被捕获的信号都是未决的,这包括没有来得及捕获(例如正在处理其他信号)和因为进程暂时屏蔽了这个信号而导致的未决。

sigpending()函数返回当前进程所有未决的集合。

extern int sigpending(sigset_t *_set);

信号集操作 教材251页

清空信号集

extern int sigemptyset(sigset_t *_set);
清空所有信号到信号集

extern int sigfillset(sigset_t *_set);

添加信号到信号集

extern int sigaddset(sigset_t *_set, int _signo);
从信号集中删除某个信号

extern int sigdelset(sigset_t *_set, int _signo);
检测信号是否在信号集中

extern int sigismember(_const sigset_t *_set, int signo);

检测信号集是否为空信号集

extern int sigisemptyset(_const sigset_t *_set);
示例程序:

1. 信号集存储结构

示例代码:

#include<signal.h>
#include<stdio.h>
#include<stdlib.h>
int output(sigset_t set);

int main()
{
	sigset_t set;
	printf("after empty the set:\n");
	sigemptyset(&set);
	output(set);

	printf("after add signo=2:\n");
	sigaddset(&set,2);
	output(set);
	printf("after add signo=10:\n");
	sigaddset(&set,10);
	output(set);
	
	sigfillset(&set);
	printf("after  fill all:\n");
	output(set);
	return 0;
}

int output(sigset_t set)
{
	int i=0;
	for(i=0;i<1;i++)	//can test i<32
	{
		printf("0x%8x\n",set.__val[i]);
		if((i+1)%8==0)
			printf("\n");
	}
}
运行结果:

$ ./a.out 
after empty the set:
0x       0
after add signo=2:
0x       2
after add signo=10:
0x     202
after  fill all:
0x7fffffff

2. 进程屏蔽信号应用示例

示例代码:

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

static void sig_quit(int);

int main(int argc,char *argv[])
{
	sigset_t    newmask, oldmask, pendmask;
	if (signal(SIGQUIT, sig_quit) == SIG_ERR)
	{ 
		perror("signal");
		exit(EXIT_FAILURE);
	}
		printf("install sig_quit\n");
		
     	// Block SIGQUIT and save current signal mask.
    	sigemptyset(&newmask);
    	sigaddset(&newmask, SIGQUIT);
   
	if (sigprocmask(SIG_BLOCK, &newmask, &oldmask) < 0)
    	{ 
		perror("signal");
		exit(EXIT_FAILURE);
	}
    	printf("Block SIGQUIT,wait 15 seconds\n");
	sleep(15);   /* SIGQUIT here will remain pending */
    	if (sigpending(&pendmask) < 0)
    	{ 
		perror("signal");
		exit(EXIT_FAILURE);
	}

   	if (sigismember(&pendmask, SIGQUIT))
        printf("\nSIGQUIT pending\n");

    	if (sigprocmask(SIG_SETMASK, &oldmask, NULL) < 0)
    	{ 
		perror("signal");
		exit(EXIT_FAILURE);
	}
    	printf("SIGQUIT unblocked\n");

    	sleep(15);   /* SIGQUIT here will terminate with core file */
   	return 0;
}

static void sig_quit(int signo)
{
    	printf("caught SIGQUIT,the process will quit\n");
    	if (signal(SIGQUIT, SIG_DFL) == SIG_ERR)
    	{ 
		perror("signal");
		exit(EXIT_FAILURE);
	}
}
运行结果:

终端1:

$ ./sigmask_example &
[3] 3303
install sig_quit
Block SIGQUIT,wait 15 seconds
终端2:

$ kill -SIGQUIT 3303
$ kill -SIGQUIT 3303
$ kill -SIGQUIT 3303
$ kill -SIGQUIT 3303
终端1:

SIGQUIT pending
caught SIGQUIT,the process will quit
SIGQUIT unblocked

3. 进程在捕捉某信号过程中屏蔽的信号

示例代码:

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

int output(sigset_t set)
{
	printf("set.val[0]=%x\n",set.__val[0]);
}

void handler(int sig)
{
	int i;
	sigset_t sysset;
	printf("\nin handler sig=%d\n",sig);
	sigprocmask(SIG_SETMASK,NULL,&sysset);
	output(sysset);			//in handler to see the process mask set
	printf("return\n");
}

int main(int argc,char *argv[])
{
	struct sigaction act;
	sigset_t set,sysset,newset;	

	sigemptyset(&set);
	sigemptyset(&newset);
	sigaddset(&set,SIGUSR1);
	sigaddset(&newset,SIGUSR2);	

	printf("\nadd SIGUSR1,the value of set:");
	output(set);	

	printf("\nadd SIGUSR2,the value of newset:");
	output(newset);	

	printf("\nafter set proc block set ,and then read to sysset\n");
	sigprocmask(SIG_SETMASK,&set,NULL);
	sigprocmask(SIG_SETMASK,NULL,&sysset);
	printf("system mask is:\n");
	output(sysset);

	printf("install SIGALRM,and the act.sa_mask is newset(SIGUSR2)\n");
	act.sa_handler=handler;
	act.sa_flags=0;
	act.sa_mask=newset;
	sigaction(SIGALRM,&act,NULL);
	pause();	

	printf("after exec ISR\n");
	sigemptyset(&sysset);
	sigprocmask(SIG_SETMASK,NULL,&sysset);
	output(sysset);
}
运行结果:

终端1:

$ ./sigaction_sigset &
[3] 3316
add SIGUSR1,the value of set:set.val[0]=200

add SIGUSR2,the value of newset:set.val[0]=800

after set proc block set ,and then read to sysset
system mask is:
set.val[0]=200
install SIGALRM,and the act.sa_mask is newset(SIGUSR2)
终端2:

$ kill -SIGALRM 3316
终端1:

in handler sig=14
set.val[0]=2a00
return
after exec ISR
set.val[0]=200


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


版权声明:本文为博主原创文章,未经博主允许不得转载。

posted @ 2014-11-08 13:19  GengLUT  阅读(131)  评论(0编辑  收藏  举报