您的位置:首页 > 运维架构 > Linux

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

2014-11-08 13:00 1041 查看
【原创】《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

内容来自用户分享和网络整理,不保证内容的准确性,如有侵权内容,可联系管理员处理 点击这里给我发消息
标签: 
相关文章推荐