【原创】《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
版权声明:本文为博主原创文章,未经博主允许不得转载。