catch signal

捕抓信号

如果信号的处理动作是用户自定义函数,在信号递达时就调用这个函数,称为捕抓信号。

除了SIGSTOP和SIGKILL进程能够忽略或捕获其他的全部信号。

注:信号可从两个不同分类角度对信号进行分类,1)可靠性方面:可靠信号与不可靠信号;2)与时间的关系上:实时信号与非实时信号。常见的信号1-31都是不可靠信号,都是非实时信号。

sighandler和main函数默认使用相同的堆栈空间,sighandler函数返回后自动执行特殊的系统调用sigreturn再次进入内核态。内核态切换到用户态执行main函数前要先扫描信号,处理信号后再执行main函数部分。

信号可以嵌套执行,这也是信号屏蔽的原因(在信号处理函数中,或关键处理时,不能被其他信号打断,从而处理其他信号)----自我理解

  • 发送信号kill

#include <signal.h>

int kill(pid_t pid, int signo);

  • 注册信号处理signal(不推荐)

#include <signal.h>

typedef void (*sighandler_t)(int);

sighandler_t signal(int signum, sighandler_t handler);

  • 发送信号sigqueue
  • 注册信号处理函数sigaction

int sigaction(int signo, const struct sigaction *act, struct sigaction *lact);

成功0, 失败-1.

注:signo不可为信号SIGKILL和SIGSTOP

struct sigaction {

void (*sa_handler)(int); /* or SIG_IGN, SIG_DFL */

sigset_t sa_mask; /*addition signals to block*/

int sa_flags; /*0则信号处理函数为sa_handler();SA_SIGINFO,信号处理函数为sa_sigaction*/

void (*sa_sigaction)(int, siginfo_t *, void *);

};

sa_mask specifies a mask of signals which should be blocked (i.e., added to the signal mask of the thread in which the signal handler is invoked) during execution of the signal handler.
In addition, the signal which triggered the handler will be blocked, unless the SA_NODEFER flag is used.

示例

主程序所有信号都注册新捕捉函数,然后捕抓函数中恢复默认动作。

19 void do_signal(int signo)

20 {

21 struct sigaction act;

22 int ret;

23

24 printf("catch signo %d.\n", signo);

25 26 act.sa_handler = SIG_DFL;

27 sigemptyset(&act.sa_mask);

28 act.sa_flags = 0;

29 ret = sigaction(signo, &act, NULL);

30 if(ret < 0){

31 perror("sigaction error");

32 exit(EXIT_FAILURE);

33 } 34 35 raise(signo);

36 }


46 int sigi;

47 int ret;

48 struct sigaction new_act;

49 50 new_act.sa_handler = do_signal;

51 sigemptyset(&new_act.sa_mask);

52 new_act.sa_flags = 0; 53 54 for(sigi=1; sigi<=SIG_NUM; sigi++){

55 if((sigi == SIGKILL) || (sigi == SIGSTOP))

56 continue; 57 58 ret = sigaction(sigi, &new_act, NULL);

59 if(ret < 0){

60 perror("main sigaction error");

61 exit(EXIT_FAILURE);

62 }else{

63 // printf("%d signal is registered.\n", sigi);

64 }

65 }

信号执行

通过编程观察到常用信号(1-31)有如下执行行为:

1)没有屏蔽任何信号时,任何信号都可以到达,并首先完成最后一个信号的执行,然后再完成原来信号函数剩余部分。(信号嵌套)

2)在信号执行过程中,再次(或多次)触发相同信号,则该信号不会立即执行(阻塞相同信号),在原来信号执行完后,仅再执行一次信号处理函数。

3)在一个信号执行周期内(程序未返回main函数执行),若执行过程中触发了多个信号,则首先执行完最后一个信号,然后倒序依次执行信号一次。

通过上述观察,可知:重复的信号仅执行一次。

究其原因,是因为非实时信号的实现方式。

当一个非实时信号发送给一个进程时,如果该信号已经在进程中注册,则该信号将被丢弃,造成信号丢失。因此,非实时信号又叫做"不可靠信号"。这意味着同一个非实时信号在进程的未决信号信息链中,至多占有一个sigqueue结构(一个非实时信号诞生后,(1)如果发现相同的信号已经在目标结构中注册,则不再注册,对于进程来说,相当于不知道本次信号发生,信号丢失;(2)如果进程的未决信号中没有相同信号,则在进程中注册自己)。

当一个实时信号发送给一个进程时,不管该信号是否已经在进程中注册,都会被再注册一次,因此,信号不会丢失,因此,实时信号又叫做"可靠信号"。这意味着同一个实时信号可以在同一个进程的未决信号信息链中占有多个sigqueue结构(进程每收到一个实时信号,都会为它分配一个结构来登记该信号信息,并把该结构添加在未决信号链尾,即所有诞生的实时信号都会在目标进程中注册)。

可参考:

http://www.ibm.com/developerworks/cn/linux/l-ipc/part2/index1.html

http://www.ibm.com/developerworks/cn/linux/l-ipc/part2/index2.html

转载于:https://www.cnblogs.com/embedded-linux/p/5017892.html

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值