嵌入式Linux系统编程 — 6.2 signal和 sigaction信号处理函数

目录

1 信号如何处理

2 signal()函数

2.1 signal()函数介绍

2.2 示例程序

3 sigaction()函数

3.1 sigaction()函数介绍

3.2 示例程序


1 信号如何处理

信号通常是发送给对应的进程,当信号到达后, 该进程需要做出相应的处理措施,可以通过以下几种方式来处理信号:

  • 忽略信号:进程可以选择忽略某些信号,使其不产生任何效果。例如,使用signalsigaction函数将信号处理函数设置为SIG_IGN。事实上,大多数信号都可以使用这种方式进行处理,但有两种信号却决不能被忽略,它们是 SIGKILL 和 SIGSTOP,它们是Linux内核保留的信号,用于立即终止和暂停进程,这两个信号的设计是为了在紧急情况下强制终止或暂停进程,确保系统能够迅速响应严重错误或管理员的干预。

  • 捕获信号:进程可以定义信号处理函数(也称为信号捕获函数或信号处理程序),当信号被发送到进程时,该函数将被调用。

  • 默认操作:如果进程没有特别指定如何处理某个信号,那么信号将执行其默认操作。例如,SIGKILL和SIGSTOP信号的默认操作是终止进程,而SIGCHLD信号的默认操作是忽略。

  • 阻塞信号:进程可以暂时阻止某些信号的传递,直到进程再次允许这些信号。这可以通过sigprocmask函数实现。

Linux 系统提供了系统调用 signal()和 sigaction()两个函数用于设置信号的处理。

2 signal()函数

2.1 signal()函数介绍

signal()函数是 Linux 系统下设置信号处理方式最简单的接口,用于定义当特定信号被触发时,进程应如何响应,可将信号的处理方式设置为捕获信号、 忽略信号以及系统默认操作。函数原型如下:

#include <signal.h>

typedef void (*sig_t)(int);
sig_t signal(int signum, sig_t handler);
  • signum:指定要设置处理方式的信号的编号。
  • handler:sig_t 类型的函数指针,指向信号对应的信号处理函数,当进程接收到信号后会自动执行该处理函数;参数 handler 既可以设置为用户自定义的函数,也就是捕获信号时需要执行的处理函数,也可以设置为 SIG_IGN 或 SIG_DFL, SIG_IGN 表示此进程需要忽略该信号, SIG_DFL 则表示设置为系统默认操作。
  • 返回值:如果成功,signal()返回指向之前信号处理函数的指针;如果失败,返回SIG_ERR

signal()函数有几个限制,包括:

  • 它不提供对信号的阻塞和非阻塞行为的控制。
  • 它不支持实时信号。
  • 它在多线程环境中可能不安全,因为它可能会改变所有线程的信号处理设置。

由于signal()函数的这些限制,现代的Linux编程推荐使用sigaction()函数,它提供了更多的控制选项,包括信号的阻塞行为、信号处理的安全性以及对实时信号的支持。

2.2 示例程序

下来编写一个简单地示例代码对signal()函数进行测试。

#include <stdio.h>
#include <stdlib.h>
#include <signal.h>    // 包含信号处理头文件
#include <unistd.h>    // 包含UNIX标准函数定义,如sleep

void sig_handler(int sig) {
    printf("Signal %d caught\n", sig);
    exit(0);
}

int main() 
{
    signal(SIGINT, sig_handler);  // 设置SIGINT的信号处理函数
    while(1) {
        printf("Running...\n");
        sleep(1);  // 暂停程序1秒
    }
    return 0;
}

示例中,当通过Ctrl+C发送SIGINT信号时,程序将调用sig_handler函数打印信号编号,然后退出。运行结果如下: 

问题思考:如果程序中没有调用 signal()函数为信号设置相应的处理方式,亦或者程序刚启动起来并未运行到 signal()处,那么这时进程接收到一个信号后是如何处理的呢?

当一个应用程序刚启动的时候(或者程序中没有调用 signal()函数) , 通常情况下, 进程对所有信号的处理方式都设置为系统默认操作。所以如果在我们的程序当中,没有调用 signal()为信号设处理方式,则默认的处理方式便是系统默认操作。所以为什么大家平时都可以使用 CTRL + C 中断符来终止一个进程,因为大部分情况下,应用程序中并不会为 SIGINT 信号设置处理方式,所以该信号的处理方式便是系统默认操作,当接收到信号之后便执行系统默认操作,而 SIGINT 信号的系统默认操作便是终止进程。

3 sigaction()函数

3.1 sigaction()函数介绍

除了signal()之外, sigaction()系统调用是设置信号处理方式的另一选择。虽然 signal()函数简单好用,而 sigaction()更为复杂,也更具灵活性以及移植性。

sigaction()允许单独获取信号的处理函数而不是设置,并且还可以设置各种属性对调用信号处理函数时的行为施以更加精准的控制,其函数原型如下所示:

#include <signal.h>

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

  • signum:指定要操作的信号的编号。
  • act:指向一个sigaction结构的指针,该结构定义了信号的新的处理方式。如果参数 act 不为 NULL,则表示需要为信号设置新的处理方式;如果参数 act 为 NULL,则表示无需改变信号当前的处理方式。
  • oldact:(可选)指向一个sigaction结构的指针,如果参数oldact 不为 NULL, 则会将信号之前的处理方式等信息通过参数 oldact 返回出来。
  • 返回值:如果成功,sigaction()返回0;如果失败,返回-1并设置errno以指示错误。

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);
};
  • void (*sa_handler)(int):信号处理函数。当信号发生时,如果sa_flags没有设置SA_SIGINFO标志,内核将调用此函数。该函数接收一个整数参数,即捕获的信号编号。

  • void (*sa_sigaction)(int, siginfo_t *, void *):指向一个更复杂的信号处理函数。如果sa_flags设置了SA_SIGINFO标志,内核将调用此函数,允许访问更详细的信号信息。它接收三个参数:信号编号、指向siginfo_t结构的指针siginfo_t 结构体用于在信号处理函数中提供有关信号的详细信息,如信号编号、错误编号等),以及一个不透明指针(通常用于传递信号处理函数的特定上下文)。

  • sigset_t sa_mask:一个信号集,定义了在信号处理函数执行期间应该被屏蔽的信号。这意味着在信号处理函数执行时,这些信号不会被传递给进程。

  • int sa_flags:参数 sa_flags 指定了一组标志,这些标志用于控制信号的处理过程,可设置为如下这些标志(多个标志使用位或" | "组合):

标志功能
SA_NOCLDSTOP如果signum为SIGCHLD, 则子进程停止时(即当它们接收到SIGSTOP、SIGTSTP、SIGTTIN 或SIGTTOU中的一种时)或恢复(即它们接收到 SIGCONT)时不会收到 SIGCHLD 信号。
SA_NOCLDWAIT如果 signum 是 SIGCHLD,则在子进程终止时不要将其转变为僵尸进程。
SA_NODEFER不要阻塞从某个信号自身的信号处理函数中接收此信号。 也就是说当进程此时正在执行某个信号的处理函数,默认情况下,进程会自动将该信号添加到进程的信号掩码字段中,从而在执行信号处理函数期间阻塞该信号, 默认情况下,我们期望进程在处理一个信号时阻塞同种信号,否则引起一些竞态条件;如果设置了 SA_NODEFER 标志,则表示不对它进行阻塞。
SA_RESETHAND执行完信号处理函数之后,将信号的处理方式设置为系统默认操作。
SA_RESTART被信号中断的系统调用,在信号处理完成之后将自动重新发起。
SA_SIGINFO如果设置了该标志,则表示使用 sa_sigaction 作为信号处理函数、而不是 sa_handler,关于 sa_sigaction信号处理函数的参数信息。
  • void (*sa_restorer)(void):指向一个在信号处理完成后调用的函数。这个成员在现代的POSIX兼容系统中已经不推荐使用,并且在许多现代系统中已经被忽略或移除。在早期的UNIX系统中,它用于指定一个函数,该函数负责在信号处理返回后恢复信号处理函数可能改变的寄存器状态。

3.2 示例程序

下面是一个使用sigaction()函数的示例程序:

#include <stdio.h>
#include <stdlib.h>
#include <signal.h>
#include <unistd.h>

// 信号处理函数
void sig_handler(int signum, siginfo_t *info, void *ptr) {
    printf("Signal %d caught\n", signum);
    if (info != NULL) {
        printf("Info: si_code=%d, si_errno=%d\n", info->si_code, info->si_errno);
    }
    // 执行清理工作,然后退出
    exit(0);
}

int main() 
{
    struct sigaction sa;

    // 初始化sigaction结构
    sa.sa_sigaction = sig_handler; // 设置信号处理函数
    sa.sa_flags = SA_SIGINFO;     // 指定使用sa_sigaction

    // 初始化信号集,这里我们不屏蔽任何信号
    if (sigemptyset(&sa.sa_mask) < 0) {
        perror("sigemptyset");
        exit(EXIT_FAILURE);
    }

    // 设置SIGINT信号的处理动作
    if (sigaction(SIGINT, &sa, NULL) < 0) {
        perror("sigaction");
        exit(EXIT_FAILURE);
    }

    printf("Waiting for SIGINT...\n");
    // 主循环,等待信号发生
    while(1) {
        sleep(1);
    }

    return 0;
}

程序定义了一个信号处理函数sig_handler,它接收三个参数:信号编号、指向siginfo_t结构的指针和一个不透明指针。在main函数中,初始化sigaction结构,并设置sa_sigactionsig_handler,将sa_flags设置为SA_SIGINFO,表示们希望使用siginfo_t结构接收信号信息。然后,调用sigaction()函数来注册SIGINT信号的处理动作。程序进入一个无限循环,等待接收SIGINT信号(通常由用户通过Ctrl+C触发)。当SIGINT信号发生时,sig_handler函数将被调用,并打印出信号信息。 运行结果如下:

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.mfbz.cn/a/764370.html

如若内容造成侵权/违法违规/事实不符,请联系我们进行投诉反馈qq邮箱809451989@qq.com,一经查实,立即删除!

相关文章

IP地址与电商企业

网购作为我们现代生活不可或缺的部分&#xff0c;现如今电商企业蓬勃发展。 IP地址是网络世界中每一台设备的独特标识符&#xff0c;就像现实世界中每家每户的门牌号。对于电商企业而言&#xff0c;它在很多方面方面发挥着作用。 IP地址能够帮助电商企业精准地确定用户所在的地…

从理论到实践的指南:企业如何建立有效的EHS管理体系?

企业如何建立有效的EHS管理体系&#xff1f;对于任何企业&#xff0c;没有安全就谈不上稳定生产和经济效益&#xff0c;因此建立EHS管理体系是解决企业长期追求的建立安全管理长效机制的最有效手段。良好的体系运转&#xff0c;可以最大限度地减少事故发生。 这篇借着开头这个…

要不要从单片机转Linux?进来看看大神怎么说

在开始前刚好我有一些资料&#xff0c;是我根据网友给的问题精心整理了一份「单片机的资料从专业入门到高级教程」&#xff0c; 点个关注在评论区回复“888”之后私信回复“888”&#xff0c;全部无偿共享给大家&#xff01;&#xff01;&#xff01;究竟要不要从单片机转Linu…

对象的引用和常引用

前面曾介绍&#xff1a;一个变量的引用就是变量的别名。实际上&#xff0c;引用是一个指针常量&#xff0c;用来存放该变量的地址。如果形参为变量的引用&#xff0c;实参为变量名&#xff0c;则在调用函数进行虚实结合时&#xff0c;把实参变量的地址传给形参&#xff08;引用…

2024 年江西省研究生数学建模竞赛题目 B题投标中的竞争策略问题---完整文章分享(仅供学习)

问题&#xff1a; 招投标问题是企业运营过程中必须面对的基本问题之一。现有的招投标平台有国家级的&#xff0c;也有地方性的。在招投标过程中&#xff0c;企业需要全面了解招标公告中的相关信息&#xff0c;在遵守招投标各种规范和制度的基础上&#xff0c;选择有效的竞争策…

工业交换机端口统计功能

工业交换机端口统计功能不仅是一项技术手段&#xff0c;更是一双透视企业网络健康状态的慧眼。通过这一功能&#xff0c;企业能够实时捕捉到网络中每一个端口的流量情况&#xff0c;这不仅仅是数据的积累&#xff0c;更是对网络脉搏的精准把握。当网络的每一个脉动都被记录在案…

【每日一练】Python遍历循环

1. 情节描述&#xff1a;上公交车(10个座位)&#xff0c;并且有座位就可以坐下 要求&#xff1a;输入公交卡当前的余额&#xff0c;只要超过2元&#xff0c;就可以上公交车&#xff1b;如果车上有空座位&#xff0c;才可以上。 seat 10 while seat > 0:money int(input(…

springboot个人证书管理系统-计算机毕业设计源码16679

摘要 随着信息技术在管理上越来越深入而广泛的应用&#xff0c;管理信息系统的实施在技术上已逐步成熟。本文介绍了个人证书管理系统的开发全过程。通过分析个人证书管理系统管理的不足&#xff0c;创建了一个计算机管理个人证书管理系统的方案。文章介绍了个人证书管理系统的系…

计算机组成原理 | CPU子系统(4)MIPS32架构-单周期处理器设计

R型运算指令通路 I型运算指令通路 I型访存指令数据通路 I型分支 J型j指令 重新布局 继续整合通路&#xff1a;MUX多路选择器 控制方式 硬连接控制方式&#xff1a;依靠电路 微命令控制&#xff1a;将指令转换为微命令 控制信号的整理和编码 控制系统的两级控制方案 ALU控制器&…

大模型时代的基础架构,大模型算力中心建设指南重磅来袭!

什么是最畅销商品&#xff1f;什么是高毛利商品&#xff1f; 我们来看一个例子&#xff1a; 一件T恤使用成本为100元的原料&#xff0c;价格为140元。另一件T恤使用成本为80元的原料&#xff0c;但在样式、颜色、图案的设计上比较有特色&#xff0c;价格也为140元。 当这两件…

【BES2500x系列 -- RTX5操作系统】深入探索CMSIS-RTOS RTX -- 同步与通信篇 -- 消息队列和邮箱处理 --(四)

&#x1f48c; 所属专栏&#xff1a;【BES2500x系列】 &#x1f600; 作  者&#xff1a;我是夜阑的狗&#x1f436; &#x1f680; 个人简介&#xff1a;一个正在努力学技术的CV工程师&#xff0c;专注基础和实战分享 &#xff0c;欢迎咨询&#xff01; &#x1f49…

面向航天器大数据安全传输的发布/订阅系统设计

源自&#xff1a;系统工程与电子技术 作者&#xff1a;覃润楠 彭晓东 谢文明 惠建江 冯渭春 姜加红 注&#xff1a;若出现无法显示完全的情况&#xff0c;可 V 搜索“人工智能技术与咨询”查看完整文章 摘 要 针对航天器试验任务过程监控的在轨故障诊断状态检测、健…

5款简洁干净,功能强悍,专注实用的软件

​ 电脑上的各类软件有很多&#xff0c;除了那些常见的大众化软件&#xff0c;还有很多不为人知的小众软件&#xff0c;专注于实用功能&#xff0c;简洁干净、功能强悍。 1.音量控制利器——EarTrumpet ​ EarTrumpet是一款专为Windows用户设计的音量控制软件。它允许用户轻松…

等保测评应该选择什么样的SSL证书

选择适合等保测评的SSL证书&#xff0c;需考虑证书的加密强度、认证机制以及是否满足国家相关的密码技术要求 1、证书类型&#xff1a;应选择符合国家或行业标准的SSL证书&#xff0c;这些证书通常采用RSA、DSA或ECC等国际认可的加密算法。同时&#xff0c;考虑到国内特定的合规…

【C语言】常见的字符串函数

©作者:末央&#xff06; ©系列:C语言初阶(适合小白入门) ©说明:以凡人之笔墨&#xff0c;书写未来之大梦 目录 strlen函数模拟实现 strstr子串查找函数模拟实现 strtok字符串分割 strlen函数 strlen函数是一个用于求字符串长度的库函数。它的参数是被求长度的字…

免费分享:2000-2021年全国分省250mNDVI数据集(附下载方法)

NDVI (Normalized Difference Vegetation Index)归一化植被指数&#xff0c;又称标准化植被指数。是目前应用最广泛的植被指数&#xff0c;与植被的分布呈线性相关&#xff0c;是植被生长状态和空间分布的最佳指示因子&#xff0c;也是遥感估算植被覆盖度(FVC&#xff0c;Fract…

VMware Workstation 安装 Centos 虚拟机

1. 下载 VMware Workstation 直接上网找官网下载即可 2. 下载 Centos 镜像 阿里巴巴开源镜像站-OPSX镜像站-阿里云开发者社区 3.打开 VMware 创建虚拟机 3.1点击创建虚拟机 3.2 选择自定义安装 3.3 选择使用 Workstation 的版本 版本越高兼容性越低但性能越好&#xff0c;一…

APP性能测试

1、性能测试分类&#xff1a;&#xff08;CPU&#xff0c;内存&#xff0c;流量&#xff0c;时间&#xff08;启动耗时计算&#xff09;&#xff0c;电量&#xff0c;流畅度&#xff08;帧率&#xff09;&#xff09;&#xff0c;稳定性&#xff08;崩溃&#xff0c;闪退&#…

[数据库原理]数据库设计(er图)

xtu期末是机试&#xff0c;所以图形表示有点不同 实体之间的关系&#xff1a; 多对多&#xff1a;可以生成一个新的关系模型一对一&#xff1a;两边都要关联一对多、多对一 &#xff1a;一的主键可以作为多的外键 如有错误&#xff0c;欢迎指正&#xff01;&#xff01;&#x…

年轻人「入侵」厂货电商:泼天的富贵or甜蜜的烦恼?

【潮汐商业评论/原创】 “明天我们带个黑色塑料袋&#xff0c;假装是批发拿货的&#xff0c;看看能不能淘到好货。这个批发‘黑话’你也学一下&#xff0c;别到时候露馅。” Paula正兴冲冲地跟Grace计划去服装批发市场“消费”。 只不过&#xff0c;与以往普通进店客人身份不…