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

【linux高级程序设计】(第十章)Linux异步信号处理机制 2

2015-07-28 20:49 686 查看

signal安装信号

typedef void (*__sighandler_t) (int);

__sighandler_t signal (int __sig, __sighandler_t __handler) :安装信号处理函数,第1个参数是收到的信号,第2个参数是处理的函数指针,返回值也是函数指针。

三个相关的宏

#define SIG_ERR ((__sighandler_t) -1) //返回错误 (语法上是把-1强制转换为了__sighandler_t型,即函数指针型)

#define SIG_DFL ((__sighandler_t) 0) //执行信号默认操作

#define SIG_IGN ((__sighandler_t) -1) //忽略信号

如果设置多次,最终生效的是最后一次设置操作。失败返回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);
}


用两个终端,一个终端执行代码,另一个终端发送信号。

发送的信号为:



处理结果为:



知识点:执行代码后面加 & 可以显示进程号

sigaction安装信号

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中不能屏蔽SIGKILLSIGSTOP信号。

如果,将成员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);
}


效果一样的

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