信号的基本属性:软中断,由内核发送,内核处理。某个进程通过内核向另一个进程发送信号时(引起信号产生的五个因素),另一个进程将会陷入内核进行中断处理,未决信号集中相应信号置1,当递达后,置0。如果阻塞信号集相应信号为1,则该信号处于未决状态。处于未决状态中的信号,多次发送时,只是执行一次,因为在未决信号集中只是记录了该信号的状态,没有记录发送的次数。信号抵达后,内核进行处理。处理方式有三:默认处理方式(5种);忽略(丢弃)和捕捉。下面说明捕捉机制。

signal和sigaction函数只是完成对一个信号进行注册的功能,而对信号的捕捉的处理都是由内核完成的。当对一个信号进行注册后,内核对其捕捉同时调用其注册时对应的用户处理函数。

1signal函数

typedef void (*sighandler_t)(int);  //定义一个函数类型 sighandler_t

sighandler_t signal(int signum, sighandler_t handler);

作用:注册一个信号捕捉函数

返回值:成功返回sighandler_t类型的函数(或函数首地址);失败则返回一个宏:SIG_ERR。注意判断该函数的返回值: sighandler ret = signal(·······);if(ret==SIG_ERR)

第一个参数为信号;第二个参数为sighandler_t类型函数(即返回值为void,形参为int)。

注意:该函数由ANSI定义,由于历史原因在不同版本的Unix和不同版本的Linux中可能有不同的行为。因此应该尽量避免使用它,取而代之使用sigaction函数。

#include <signal.h>
#include <stdio.h>
#include <errno.h>
#include <stdlib.h>
#include <unistd.h>typedef void (*sighandler_t) (int);  //定义sighandler_t类型void catchsigint(int signo)
{printf("-----------------catch\n");
}int main(void)
{sighandler_t handler;handler = signal(SIGINT, catchsigint);  //注册2号信号if (handler == SIG_ERR) {perror("signal error");exit(1);}                            //判断返回值while (1);return 0;
}

[root@localhost 01_signal_test]# ./signal2

^C-----------------catch                 //Ctrl+C

^C-----------------catch                 //Ctrl+C

^\Quit (core dumped)                 //Ctrl+\

只要一发送2号信号,就会执行相应函数。

2sigaction函数

int sigaction(int signum, const struct sigaction *act, struct sigaction *oldact);

作用:对某个信号进行注册(同signal),即对某个信号之前对应的处理方式(函数)进行修改。

返回值:成功0;失败-1,设置errno。

参数:

act传入参数,新的处理方式。

oldact传出参数,旧的处理方式。

struct sigaction结构体:

struct sigaction {

 void     (*sa_handler)(int);

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

  sigset_t   sa_mask;

        int       sa_flags;

void     (*sa_restorer)(void);

};   //最后一个成员不用(舍弃了);第二成员不常用

sa_restorer:该元素是过时的,不应该使用,POSIX.1标准将不指定该元素。(弃用)

sa_sigaction:当sa_flags被指定为SA_SIGINFO标志时,使用该信号处理程序。(很少使用)

重点掌握:

sa_handler:指定信号捕捉后的处理函数名(即注册函数)。也可赋值为SIG_IGN表忽略 SIG_DFL表执行默认动作;

sa_mask: 调用信号处理函数时,所要屏蔽的信号集合(信号屏蔽字)。注意:仅在处理函数被调用期间屏蔽生效,是临时性设置;sa_mask也是一个字(64位),只是在执行相应的用户处理函数期间生效。即在执行用户处理函数期间, sa_mask屏蔽的信号也不能递达,处于未决状态。如果sa_mask未屏蔽,则响应信号,中断嵌套。相当于此期间,sa_mask代替了mask。

sa_flags:通常设置为0,表示用默认属性。默认属性即为:sa_mask中将自己屏蔽,即该信号的注册函数执行期间,再次向进程发送该信号,该信号不能递达,处于未决状态。

最后一个参数如果不关心之前的处理方式,可以为NULL

3)信号捕捉机制

进程正常运行时,默认PCB中有一个信号屏蔽字,假定为mask,它决定了进程自动屏蔽哪些信号。当注册了某个信号捕捉函数,捕捉到该信号以后,要调用该函数。而该函数有可能执行很长时间,在这期间所屏蔽的信号不由mask来指定。而是用sa_mask来指定。调用完信号处理函数,再恢复为mask。

sa_flags为0时,XXX信号捕捉函数执行期间,XXX信号自动被屏蔽。

阻塞的常规信号(1-31)不支持排队,产生多次只记录一次。(后32个实时信号支持排队)

内核实现信号捕捉的过程如下:

首先,处于用户态(user mode)的某个进程在执行到某个指令时突然接收某个信号(软中断,终端按键产生;硬件异常产生;命令产生;系统调用产生或者软件条件产生),会暂停执行下一条指令而陷入内核进入内核态。

内核在处理这一异常后,在准备会用户态之前先处理可以递达该进程的信号。

如果该信号的处理方式为捕捉,则内核对该信号进行捕捉,同时调用相应的用户处理函数,回到用户态执行相应的用户处理函数(注意不是回到主控制流程)。

在用户处理函数执行完返回时,再次执行系统调用sigretum再次进入内核。因为函数执行完需要返回到该函数的调用点,而该函数是内核调用的,因此需要再次返回到内核。

最后,从内核再次返回到用户模式,从上次中断处继续执行下一条指令。

//练习1:为某个信号设置捕捉函数;验证在信号处理函数执行期间,该信号多次递送,那么只在处理函数之行结束后,处理一次;验证sa_mask在捕捉函数执行期间的屏蔽作用。

#include <stdio.h>
#include <unistd.h>
#include <stdlib.h>
#include <signal.h>void docatch(int signo)  //用户处理函数
{printf("the %dth signal is catched\n", signo);sleep(10); printf("-------finish------\n");
}
int main(void)
{int ret;struct sigaction act;act.sa_handler = docatch;sigemptyset(&act.sa_mask);sigaddset(&act.sa_mask, SIGQUIT);  //sa_mask屏蔽字中,3号信号置1act.sa_flags = 0;  //默认属性   信号捕捉函数执行期间,自动屏蔽本信号ret = sigaction(SIGINT, &act, NULL);   //注册2号信号if (ret == -1) {perror("sigaction error");exit(1);}while (1);return 0;
}

[root@localhost 01_signal_test]# ./test_sigac

^Cthe 2th signal is catched   // 2号信号 Ctrl +C

-------finish------

^Cthe 2th signal is catched  // 2号信号 Ctrl +C

^C^C^C^C^C^C^C^C^C^C^C^C^C-------finish------   // 执行期间,发多个2号信号

the 2th signal is catched

-------finish------            //但是只是执行了一次

^Cthe 2th signal is catched

^\^\^\^\^\^\^\^\^\^\^\^\-------finish------   // 执行期间,发多个3号信号

Quit (core dumped)   //2号信号处理完后,处理2号,则退出进程,结束。

信号捕捉(signal、sigaction)相关推荐

  1. 2信号处理之:信号产生原因,进程处理信号行为,信号集处理函数,PCB的信号集,sigprocmask()和sigpending(),信号捕捉设定,sigaction,C标准库信号处理函数,可重入函数,

     1信号产生原因 2.进程处理信号行为 manpage里信号3中处理方式: SIG_IGN SIG_DFL                                            默 ...

  2. Linux系统编程----7(信号集,信号屏蔽,信号捕捉)

    信号集操作函数 内核通过读取未决信号集来判断信号是否应被处理.信号屏蔽字 mask 可以影响未决信号集.而我们可以在应 用程序中自定义 set 来改变 mask.已达到屏蔽指定信号的目的. 信号集设定 ...

  3. linux signal函数用法,linux信号机制之sigaction构造体浅析,signal 函数,信号捕捉.

    来自:http://hi.baidu.com/phenix_yw/blog/item/6eb4ca391d1479f23a87ce19.html 信号安装函数sigaction(int signum, ...

  4. linux操作系统信号捕捉函数之sigaction用法小结

    (1)sigaction函数:注册一个信号捕捉函数(不参与捕捉信号,信号由内核捕捉),并修改原来的信号处理动作 (2)函数原型及头文件 头文件:#include<signal.h> 函数原 ...

  5. linux的基础知识——signal信号捕捉,信号集操作函数

    文章目录 1.signal捕捉信号 2.信号集操作函数 3.sigprocmask函数 4.sigpending函数 5.例子1:打印某个进程未决信号集 6.例子2:signal函数的注册捕捉执行函数 ...

  6. 信号的捕捉与sigaction函数

    一.内核如何实现信号的捕捉 如果信号的处理动作是用户自定义函数,在信号递达时就调用这个函数,这称为捕捉信号.由于信号处理函数的代码是在用户空间的,处理过程比较复杂,举例如下: 1. 用户程序注册了SI ...

  7. 信号、signal 函数、sigaction 函数

    文章目录 1.信号的基本概念 2.利用 kill 命令发送信号 3.信号处理的相关动作 4.信号与 signal 函数 4.1 signal 函数示例一 4.2 signal 函数示例二 5.利用 s ...

  8. linux系统编程之信号(四):信号的捕捉与sigaction函数

    一.内核如何实现信号的捕捉 如果信号的处理动作是用户自定义函数,在信号递达时就调用这个函数,这称为捕捉信号.由于信号处理函数的代码是在用户空间的,处理过程比较复杂,举例如下: 1. 用户程序注册了SI ...

  9. Linux 信号signal\sigaction

    转发:作者,故事狗 https://www.jianshu.com/p/f445bfeea40a Linux 信号signal 对于 Linux来说,实际信号是软中断,许多重要的程序都需要处理信号.信 ...

最新文章

  1. go 语言 链表 的增删改查
  2. 迁移学习之MobileNet(88层)和MobileNetV2(88层)
  3. CentOS 6.8 GRUB加密-修复和破解密码实战指南
  4. 开关稳压电源过热(高温)保护功能作用--来自中港扬盛分享干货
  5. AD19 add pins to nets错误_《英雄联盟手游》错误代码问题大全 LOL的错误代码都是什么意思...
  6. Java知识点总结(反射-获取类的信息)
  7. java数组的初始化方式
  8. 【图像处理】图像灰度级减少, 图像缩放(Reducing the Number of Gray Levels, Zooming and Shrinking)
  9. 为什么被喷的总是产品经理?
  10. 接口测试之发包工具介绍
  11. 【EVE模拟器是干什么的】
  12. Wallys/QCA9531,MIMO,2.4G,30dBm
  13. 如何注册Gitlab/被墙如何注册
  14. 在线hash密码破解网站列表
  15. 拒绝平庸,这10个鲜为人知的实用网站,让你受益无穷!
  16. Excel/WPS做数据透视表,即对变量做交叉汇总(列联表)
  17. DCN DCSW-6028-pro 内部portal认证
  18. 机器人中欧拉角,偏航角、俯仰角、横滚角的自锁现象与四元数的来源于推导
  19. localhost无法访问本机
  20. 创建C++字符串最常用的五种方法,难吗?有手就行!

热门文章

  1. smarty引擎之练习
  2. Android-Universal-Image-Loader三大组件DisplayImageOptions、ImageLoader、ImageLoaderConfiguration详解...
  3. 调光设备术语:调光曲线(转)
  4. [Android] (在ScrollView里嵌套view)重叠view里面的onTouchEvent的调用方法
  5. 单击浏览器右上角的X弹出提示窗口
  6. Spring MVC+Ant+Tomcat+Eclipse最简单的demo
  7. 看了本书《答案在你心中》里面的很多问题都蛮有意思!!!
  8. js转json工具_菜鸟丨Egert3D微信小游戏发布与Unity工具使用
  9. python列表字符串转数字_python 将列表中的字符串转为数字
  10. solaris配置php,Solaris下安装Oracle_启动Oracle及监听