标签:
typedef void (*__sighandler_t) (int);
__sighandler_t signal (int __sig, __sighandler_t __handler) :安装信号处理函数,第1个参数是收到的信号,第2个参数是处理的函数指针,返回值也是函数指针。
三个相关的宏
如果设置多次,最终生效的是最后一次设置操作。失败返回SIG_ERR
#include<stdio.h> #include<unistd.h> #include<signal.h> void sig_usr(int sig); int main() { int i = 0; if(signal(SIGUSR1, sig_usr) == SIG_ERR) printf("Cannont catch SIGUSR1\n"); if(signal(SIGUSR2, sig_usr) == SIG_ERR) printf("Cannont catch SIGUSR2\n"); while(1) { printf("%2d\n", i); pause(); //等待有信号到来 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); }
用两个终端,一个终端执行代码,另一个终端发送信号。
发送的信号为:
处理结果为:
知识点:执行代码后面加 & 可以显示进程号
int sigaction (int __sig, struct sigaction * __act, struct sigaction *__oact)
其中sigaction结构体的定义为:
struct sigaction{ union{ __sighandler_t _sa_handler; //SIG_DFL, SIG_IGN 信号,类似signal函数 void (*_sa_sigaction)(int, struct siginfo *, void *); //信号捕获函数,可以获取其他信息 }__u; sigset_t sa_mask; //执行信号捕获函数期间要屏蔽的其他信号集 unsigned long sa_flags; //影响信号行为的特殊标志 void (*sa_restorer)(void); //没有使用 }; #define sa_handler _u._sa_handler //对两个成员进行重定义 #define sa_sigaction _u._sa_sigaction
屏蔽信号集sa_mask中不能屏蔽SIGKILL和SIGSTOP信号。
如果,将成员sa_flags设置为SA_SIGINFO, 则通过sa_sigaction设置信号处理函数。其函数指针类型为:
void (*_sa_sigaction)(int, struct siginfo *, void *); //信号捕获函数,可以获取其他信息
第一个参数:对应信号
第三个参数:赋给指向ucontext_t类型的一个对象的指针,以引用在传递信号时被中断的接收进程或线程的上下文。
第二个参数,struct siginfo 描述信号中断的部分信息。具体结构体定义如下:
si_sigo成员包含系统生成的信号编码。
si_errno成员可能包含与实现相关的其他错误信息。如果不为0,则该成员将包含一个错误编号,用于表示导致生成该信号的条件
si_code成员包含一个标识该信号生成原因的代码
后续的联合体不同的信号将填充不同的部分。
例子:
#include<stdio.h> #include<unistd.h> #include<signal.h> #include<stdlib.h> void func(int signo, siginfo_t *info, void *p) { printf("signo = %d\n", signo); printf("sender pid = %d\n", info->si_pid); //打印发送者的pid } int main() { struct sigaction act, oact; sigemptyset(&act.sa_mask); //设置掩码为空 act.sa_flags = SA_SIGINFO; //需要修改sa_flags act.sa_sigaction = func; //处理函数 sigaction(SIGUSR1, &act, &oact); //安装信号 while(1) { printf("pid is %d Hello world.\n", getpid()); pause(); //等待一个信号 } }
发送信号的终端
执行代码的终端
后面有一大段关于sa_flags的说明,没仔细看。
对比sigaction的sa_handler和signal
先屏蔽信号,给自己发信号,解除屏蔽
signal
#include<stdlib.h> #include<signal.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; //安装信号处理函数 if(signal(SIGUSR1, sig_usr1) < 0 || signal(SIGUSR2, sig_usr2) || signal(SIGALRM, sig_alarm)) perror("signal\n"); sigemptyset(&newmask); //掩码置空 sigaddset(&newmask, SIGUSR1); sigaddset(&newmask, SIGUSR2); sigaddset(&newmask, SIGALRM); 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有bug,信号会执行很多次,但我这里没问题啊?
sigaction的
#include<stdlib.h> #include<signal.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) { struct sigaction act1, act2, act3; act1.sa_handler = sig_usr1; sigemptyset(&act1.sa_mask); act2.sa_handler = sig_usr2; sigemptyset(&act2.sa_mask); act3.sa_handler = sig_alarm; sigemptyset(&act3.sa_mask); //安装信号处理函数 sigaction(SIGUSR1, &act1, NULL); sigaction(SIGUSR2, &act2, NULL); sigaction(SIGALRM, &act3, NULL); sigset_t newmask, oldmask; sigemptyset(&newmask); //掩码置空 sigaddset(&newmask, SIGUSR1); sigaddset(&newmask, SIGUSR2); sigaddset(&newmask, SIGALRM); sigprocmask(SIG_BLOCK, &newmask, &oldmask); printf("SIGUSR is blocked\n"); kill(getpid(), SIGUSR2); kill(getpid(), SIGUSR1); kill(getpid(), SIGALRM); sigprocmask(SIG_SETMASK, &oldmask, NULL); }
效果一样的
【linux高级程序设计】(第十章)Linux异步信号处理机制 2
标签:
原文地址:http://www.cnblogs.com/dplearning/p/4684293.html