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


【原创】《Linux高级程序设计》杨宗德著 - 进程管理与程序开发 - 安装信号与捕捉信号


信号处理办法 

(1)忽略此信号。大多数信号都可使用这种方式进行处理,但有两种信号不能被忽略,SIGKILL和SIGSTOP。这两种信号不能被忽略的原因是:它们向超级用户提供一种使进程终止或停止的可靠方法。
(2)捕捉信号。通知内核在某种信号发生时调用一个用户函数。在用户函数中,可执行用户希望对这种事件进行的处理,这需要安装此信号。例如捕捉到SIGCHLD信号,则表示子进程已经终止,所以此信号的捕捉函数可以调用waitpid()以取得该子进程的进程PID以及它的终止状态和资源。
(3)执行系统默认操作。Linux系统对任何一个信号都规定了一个默认的操作。 

signal安装信号


示例代码:

#include <stdio.h>
#include <unistd.h>
#include <signal.h>
void sig_usr(int sig);

int main(int argc,char *argv[])
{ 
	int i = 0;
  	if(signal(SIGUSR1,sig_usr) == SIG_ERR)
    		printf("Cannot catch SIGUSR1\n");
 	if (signal(SIGUSR2,sig_usr) == SIG_ERR)
    		printf("Cannot catch SIGUSR2\n");
	while(1)
	{
		printf("%2d\n", i);
    		pause(); 
    		/* pause until signal handler
       		has processed signal */
   		i++;
  	}
  	return 0;
}

void sig_usr(int sig)
{
	if (sig == SIGUSR1)
   		printf("Received SIGUSR1\n");
  	else if (sig == SIGUSR2)
    		printf("Received SIGUSR2\n");
  	else
    		printf("Undeclared signal %d\n", sig);
}
运行结果:

第一个终端执行:

$ ./a.out &
[1] 3017
第二个终端执行:

$ kill -SIGUSR1 3017
$ kill -SIGUSR2 3017
$ kill -SIGABRT 3017
第一个终端结果:

$  0
Received SIGUSR1
 1
Received SIGUSR2
 2

[1]+  已放弃               (核心已转储) ./a.out

sigaction安装信号


struct_sigaction结构


示例代码:

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

void myHandler(int sig);

int main(int argc,char *argv[])
{ 
  	struct sigaction act, oact;

  	act.sa_handler = myHandler;
  	sigemptyset(&act.sa_mask); /*initial. to empty mask*/
  	act.sa_flags = 0;
  	sigaction(SIGUSR1, &act, &oact); 
    	while (1) 
	{ 
		printf("Hello world.\n"); 
		pause();
	}
}

void myHandler(int sig)
{
	printf("I got signal: %d.\n", sig);
}
// to end program, <Ctrl + \> to generate SIGQUIT
运行结果:

终端1:

$ ./a.out &
[1] 3122
$ Hello world.
终端2:

$ kill -SIGUSR1 3122
终端1:

I got signal: 10.
Hello world.

测试sa_sigaction

示例代码:

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

void func(int signo, siginfo_t *info, void *p)
{
	printf("signo=%d\n",signo);
	printf("sender pid=%d\n",info->si_pid);
}

int main(int argc,char *argv[])
{ 
  	struct sigaction act, oact;

  	sigemptyset(&act.sa_mask); /*initial. to empty mask*/
  	act.sa_flags = SA_SIGINFO;
	act.sa_sigaction=func;
  	sigaction(SIGUSR1, &act, &oact); 
    	while (1) 
	{ 
		printf("pid is %d Hello world.\n",getpid()); 
		pause();
	}
}
运行结果:

终端1:

$ ./a.out &
[2] 3159
$ pid is 3159 Hello world.
终端2:

$ kill -SIGUSR1 3159

终端1:

signo=10
sender pid=3029
pid is 3159 Hello world.

sa_flags说明

教材248页。

signal的系统漏洞

示例代码:

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

static void sig_usr1(signo)
{
	printf("SIGUSR1 function\n");
}
static void sig_usr2(signo)
{
	printf("SIGUSR2 function\n");
}
static void sig_alarm(signo)
{
	printf("SIGALRM function\n");
}

int main(void)
{
	sigset_t newmask,oldmask;
	/*-----signal ------------------*/	
	if(signal(SIGUSR1,sig_usr1) <0|signal(SIGUSR2,sig_usr2) <0 |signal(SIGALRM,sig_alarm) <0)
		perror("signal\n");
	sigemptyset(&newmask);
	sigaddset(&newmask,SIGUSR1);
	sigaddset(&newmask,SIGUSR2);
	sigaddset(&newmask,SIGALRM );
	/*---------signal end--------------*/	

	/*-----sigaction------------------*/	
	/*struct sigaction act1,act2,act3;
	act1.sa_handler=sig_usr1;
	sigemptyset(&act1.sa_mask);<pre name="code" class="cpp"><span style="white-space:pre">	</span>act1.sa_flags=0;//没有这句,执行后会出现段错误
act2.sa_handler=sig_usr2;sigemptyset(&act2.sa_mask);
<span style="white-space:pre">	</span>act2.sa_flags=0;
act3.sa_handler=sig_alarm;
	sigemptyset(&act3.sa_mask);
<span style="white-space:pre">	</span>act3.sa_flags=0;;
sigaction(SIGUSR1,&act1,NULL);sigaction(SIGUSR2,&act2,NULL);sigaction(SIGALRM,&act3,NULL);*//*-----sigaction--end----------------*/sigprocmask(SIG_BLOCK,&newmask,&oldmask);printf("SIGUSR is blocked\n");kill(getpid(),SIGUSR2);kill(getpid(),SIGUSR1);kill(getpid(),SIGALRM);sigprocmask(SIG_SETMASK,&oldmask,NULL);}


用signal设置信号处理方式,发送一次SIGUSR1,SIGUSR2,却执行了两次信号处理函数。(书上是这样说的,但是我在Ubuntu12.04中运行时,却没有出现这种漏洞的情况。)

运行结果(书上说的结果,与我运行时的结果不一致):

$ ./a.out 
SIGUSR is blocked
SIGALRM function
SIGUSR2 function
SIGUSR1 function<pre name="code" class="cpp">SIGALRM function
SIGUSR2 function
<pre name="code" class="cpp" style="font-size:18px;">SIGUSR1 function<pre name="code" class="cpp" style="font-size:18px;">SIGUSR1 function




用sigaction设置信号处理方式只会执行一次。

运行结果:

$ ./a.out 
SIGUSR is blocked
SIGALRM function
SIGUSR2 function
SIGUSR1 function

注意:

1. 在某些版本的UNIX系统中,在执行完一次信号处理后有可能需要再次执行此信号的安装,因此,建议在handler函数中再次安装handler信号处理函数。当然,在目前版本的Linux系统中可以不这样做。

2. signal一般不建议使用,建议使用sigaction代替。

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


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

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