捕抓信号

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

除了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

catch signal的更多相关文章

  1. Signal ()函数详细介绍

    1. 功能 设置某一信号的对应动作 2. 声明 #include <signal.h> typedef void (*sighandler_t)(int); sighandler_t si ...

  2. signal()信号操作

    一.函数描述 #include <signal.h> typedef void (*sighandler_t)(int);sighandler_t signal(int signum, s ...

  3. gdb 常用内容

    gdb exegdb exe coregdb -p info m TAB ^関数の先頭 info b ^list the breakpoint set args -a test ^引数設定 show ...

  4. Linux信号

    信号本质上就是一个软件中断,它既可以作为两个进程间的通信的方式, 更重要的是, 信号可以终止一个正常程序的执行, 通常被用于处理意外情况 ,* 信号是异步的, 也就是进程并不知道信号何时会到达 $ki ...

  5. Linux信号基础

    Linux信号基础   作者:Vamei 出处:http://www.cnblogs.com/vamei 欢迎转载,也请保留这段声明.谢谢! Linux进程基础一文中已经提到,Linux以进程为单位来 ...

  6. Linux 进程

    Linux 进程 在用户空间,进程是由进程标识符(PID)表示的.从用户的角度来看,一个 PID 是一个数字值,可惟一标识一个进程.一个 PID 在进程的整个生命期间不会更改,但 PID 可以在进程销 ...

  7. Linux进程间通信-信号

    1.什么是信号信号是Linux系统响应某些条件而产生的一个事件,接收到该信号的进程会执行相应的操作. 2.信号的产生1)由硬件产生,如从键盘输入Ctrl+C可以终止当前进程2)由其他进程发送,如可在s ...

  8. MySQL在ROW模式下通过binlog提取SQL语句

    Linux基于row模式的binlog,生成DML(insert/update/delete)的rollback语句通过mysqlbinlog -v 解析binlog生成可读的sql文件提取需要处理的 ...

  9. Linux简单程序实例(GNU工具链,进程,线程,无名管道pipe,基于fd的文件操作,信号,scoket)

    一, GNU工具链简介: (1)编译代码步骤: 预处理 -> 编译 -> 汇编 -> 链接: 预处理:去掉注释,进行宏替换,头文件包含等工作: gcc -E test.c -o te ...

随机推荐

  1. JVisualVM简介与内存泄漏实战分析

    JVisualVM简介与内存泄漏实战分析 学习了:https://blog.csdn.net/kl28978113/article/details/53817827

  2. 【python】如何安装BeautifulSoup4

    在cmd窗口输入 pip install beautifulsoup4,如下: C:\Users\horn1\Desktop\python\3>pip install beautifulsoup ...

  3. (C++)已知String类的定义,实现其函数体

    CString类的定义如下: class CMyString{ public: CMyString(const char* pData=NULL); CMyString(const CMyString ...

  4. angularjs中使用$q.defer

    方法method1和方法method2的区别,我还正在研究中...待添加 代码如下: <html ng-app="myApp"> <head> <ti ...

  5. ipkg包管理

    添加ipkg更新源 你可以通过修改/opt/etc/ipkg.conf去添加 ############################ echo src optware http://ipkg.nsl ...

  6. FileItem 出现部分中文乱码解决办法

    首先要进行两处的修改: 第一:如果你使用了上传文件的包, 如:ServletFileUpload sfu = new ServletFileUpload(factory); sfu.setHeader ...

  7. Oracle 检索数据

    SELECT  *  |    {   [ DISTINCT  ]    column   |    expression   [   alias   ]  ,   ...    } FROM  ta ...

  8. Project Euler:Problem 76 Counting summations

    It is possible to write five as a sum in exactly six different ways: 4 + 1 3 + 2 3 + 1 + 1 2 + 2 + 1 ...

  9. Python 更新dict

    更新dict 对需要更新的key-value 直接赋值即可dict是可变的,也就是说,我们可以随时往dict中添加新的 key-value.比如已有dict:d = { 'Adam': 95, 'Li ...

  10. 【LeetCode】76. Minimum Window Substring

    Minimum Window Substring Given a string S and a string T, find the minimum window in S which will co ...