Linux系统编程—信号捕捉

董昭
• 阅读 3275

前面我们学习了信号产生的几种方式,而对于信号的处理有如下几种方式:

  1. 默认处理方式;
  2. 忽略;
  3. 捕捉。

信号的捕捉,说白了就是抓到一个信号后,执行我们指定的函数,或者执行我们指定的动作。下面详细介绍两个信号捕捉操作参数:signalsigaction

signal函数

函数原型:

sighandler_t signal(int signum, sighandler_t handler);

其中,sighandler定义是这样的:typedef void (*sighandler_t)(int);

函数作用:

注册一个信号捕捉函数,也就是说,收到了某个信号,就执行它所注册的回调函数。

函数参数:

signum:信号编号,尽量用宏来写,而别用数字,这样更适合跨平台;

handler:注册的回调函数;

函数缺陷:

由于历史原因,该函数在不同版本的Unix和Linux系统中可能起到的效果不一样,所以跨平台性不佳,尽量避免使用它,取而代之使用通用性更好的sigaction函数。

 #include <stdio.h>
 #include <signal.h>
 
 void func()
 {
     printf("SIGQUIT catched!\n");
 }
 
 int main()
{
    signal(SIGQUIT, func);
    while(1);
}

sigaction函数

函数原型:

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

函数作用:

与signal函数类似,用来注册一个信号捕捉函数;

返回值:

成功:0;失败:-1,并设置errno;

参数:

signum:信号编号,尽量用宏来写,而别用数字,这样更适合跨平台;

act:传入参数,新的信号捕捉方式;

oldact:传出参数,旧的信号捕捉方式

这里特别要注意参数中struct sigaction结构体,这也是这个函数的难点所在,下面详细说明:

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和sa_sigaction这两个成员一个已经被弃用了,另一个很少使用,所以我们暂且不管它们,重点掌握剩下的三个。

sa_handler:指定信号捕捉后的处理函数,即注册回调函数。该成员也可以赋值为SIG_IGN,表示忽略该信号,也可注册为SIG_DFL,表示执行信号的默认动作。

sa_mask:临时阻塞信号集(或信号屏蔽字)先来看这样一个情景:

某个信号已经注册了回调函数,当内核传递这个信号过来时,会先经过一个阻塞信号集,先阻塞掉部分信号。再去执行对应的回调函数。如下图示:

Linux系统编程—信号捕捉

假如说,这个回调函数回调执行的时间比较长,比如2秒,在这2秒里,又有其它的信号过来,那进程是暂停当前回调函数,去响应新的信号,还是不管新来的信号,先把当前回调函数处理完再说?

正确的做法是,在执行回调函数期间,使用sa_mask临时的去替代进程的阻塞信号集,保证回调函数安心的执行完毕,再解除替代。注意:这个过程仅仅发生在回调函数执行期间,是临时性的设置。

sa_flags:通常设置为0,表示使用默认属性。

再来看另外一个场景:

比如进程对SIGQUIT注册了回调函数,当回调函数在执行期间,又来了SIGQUIT函数,这时,进程是响应还是不响应该信号?这就是sa_flags的一个作用,当其设置为0时,表示使用默认属性,也就是先不响应该信号,而是执行完回调函数再处理此信号。

另外,阻塞的常规信号不支持排队,也就是说,执行回调函数期间,再来千百个同个信号时,系统只记录一次。而后面的32个实时信号则支持排队。

 #include <stdio.h>
 #include <signal.h>
 #include <unistd.h>
 
 void func(int signal)
 {
     printf("SIGQUIT catched!\n");
     sleep(2);   //用来模拟回调函数执行很长时间
     printf("func finished!\n");
}

int main()
{
    struct sigaction act;
    act.sa_handler = func;
    sigemptyset(&act.sa_mask);  //先清空临时阻塞信号集
    sigaddset(&act.sa_mask, SIGINT);    // 执行回调函数期间,屏蔽SIGINT
    act.sa_flags = 0;

    sigaction(SIGQUIT, &act, NULL); //注册回调函数

    while(1);

    return 0;
}

更多精彩内容,请关注公众号良许Linux,公众内回复1024可免费获得5T技术资料,包括:Linux,C/C++,Python,树莓派,嵌入式,Java,人工智能,等等。公众号内回复进群,邀请您进高手如云技术交流群。

Linux系统编程—信号捕捉


最后,最近很多小伙伴找我要Linux学习路线图,于是我根据自己的经验,利用业余时间熬夜肝了一个月,整理了一份电子书。无论你是面试还是自我提升,相信都会对你有帮助!

免费送给大家,只求大家金指给我点个赞!

电子书 | Linux开发学习路线图

也希望有小伙伴能加入我,把这份电子书做得更完美!

有收获?希望老铁们来个三连击,给更多的人看到这篇文章

推荐阅读:

点赞
收藏
评论区
推荐文章
还在为图虫开屏广告效率烦恼?看这篇就够了!
灵活性是指让系统能够选择最有价值的广告展示机会和最有可能表现最好的素材,及时的传递给适合的人。在看来,提升ROI的核心在于广告效率,而:广告效率灵活性X信号而信号是机器学习模型用来做出决策是否会有转化的行为模型。两个关键词,转化(用户是否跟广告做了互动)、事件(优化的行为及频率)如果让我们的系统有适当的灵活性去学习你们最在意的结果信号数据,我们才能根
Ricky Ricky
4年前
PyQt5 快速开发与实战(二)
3.4信号与槽关联1.信号signal与slot是Qt的核心机制。2.如何为控件发射的信号指定对应的处理槽函数?1.在窗口的UI设计中添加信号
还在为图虫开屏广告效率烦恼?看这篇就够了!
灵活性是指让系统能够选择最有价值的广告展示机会和最有可能表现最好的素材,及时的传递给适合的人。在看来,提升ROI的核心在于广告效率,而:广告效率灵活性X信号而信号是机器学习模型用来做出决策是否会有转化的行为模型。两个关键词,转化(用户是否跟广告做了互动)、事件(优化的行为及频率)如果让我们的系统有适当的灵活性去学习你们最在意的结果信号数据,我们才能根
Stella981 Stella981
3年前
OpenCV 应用(1)卡尔曼滤波跟踪
0卡尔曼OPENCV预测鼠标位置卡尔曼滤波不要求信号和噪声都是平稳过程的假设条件。对于每个时刻的系统扰动和观测误差(即噪声),只要对它们的统计性质作某些适当的假定,通过对含有噪声的观测信号进行处理,就能在平均的意义上,求得误差为最小的真实信号的估计值。因此,自从卡尔曼滤波理论问世以来,
Stella981 Stella981
3年前
Linux 信号signal处理机制
信号是Linux编程中非常重要的部分,本文将详细介绍信号机制的基本概念、Linux对信号机制的大致实现方法、如何使用信号,以及有关信号的几个系统调用。信号机制是进程之间相互传递消息的一种方法,信号全称为软中断信号,也有人称作软中断。从它的命名可以看出,它的实质和使用很象中断。所以,信号可以说是进程控制的一部分。一、信号的基本概念本节
Stella981 Stella981
3年前
Nginx之进程间的通信机制(共享内存、原子操作)
1\.概述Linux提供了多种进程间传递消息的方式,如共享内存、套接字、管道、消息队列、信号等,而Nginx框架使用了3种传递消息的传递方式:共享内存、套接字、信号。在进程间访问共享资源时,还需要提供一种机制使各个进程有序、安全地访问资源,避免并发访问带来的未知结果。Nginx主要使用了3种同步方式:原子操作、信号量、
Stella981 Stella981
3年前
Linux 进程后台运行的方法
当用户注销(logout)或者网络断开时,终端会收到HUP(hangup)信号从而关闭其所有子进程。因此,我们的解决办法就有两种途径:要么让进程忽略HUP信号,要么让进程运行在新的会话里从而成为不属于此终端的子进程。nohupnohup的用途就是让提交的命令忽略hangup信号。nohup的使用是十分方便的,只需在要处理
Stella981 Stella981
3年前
CanOpen学习笔记3
主机部分(Master):从机PDO发送发送或者接收需要SYNC信号,也就是从机接收到一个或者多个SYNC信号后发送一个PDO,也可以主机明确给出请求信号。SYNC同步信号产生设置:1、写0x40000080到index0x1005,subindex0位置(SYNCCOBID)。2、设置同步信号周期,在index0x1006,s
Wesley13 Wesley13
3年前
PHP的超时实现
我们知道PHP可以设置一个脚本执行的超时时间,也就是脚本的执行时间不能超过设置的超时时间.那么PHP是怎么做到这个功能的呢?  其实PHP的超时功能利用了操作系统的定时信号来实现的,在一个请求开始时(php\_request\_startup),PHP便会利用zend\_set\_timeout()接口来设置一个定时器信号,
铁扇公主 铁扇公主
1年前
简单好用的wifi管理工具 WiFi Signal 激活最新版
WiFiSignal是一款用于测量和监测WiFi信号强度的软件工具。该软件可用于Windows、Mac和移动设备上,它提供了实时的WiFi信号强度图表和详细的信号参数,帮助用户优化无线网络连接和确定最佳的WiFi覆盖范围。以下是WiFiSignal可能提供
九路 九路
1年前
linux nohup命令使用教程
nohup的作用可以将程序以忽略挂起信号(SIGHUP)的方式运行。常见的用法是和&命令一同使用,将命令放置到后台运行,即使终端挂掉,进程会忽略挂起信号,继续运行。平时我们直接执行命令,只是在终端中运行,如果关闭了终端,我们的命令也就结束了。尤其是服务,需