Linux - 信号

news2024/11/12 14:35:52

文章目录

    • 一、信号的定义
    • 二、查看信号
    • 三、产生信号
      • 1、指令
      • 2、系统调用
      • 3、由软件条件产生信号
      • 4、异常
      • 5、键盘输入
    • 四、保存信号
      • 1、补充:信号其他相关概念
      • 2、信号保存在哪,怎么保存?
      • 3、信号集操作函数
    • 五、捕获信号
      • 1、概念
      • 2、捕获信号的时机
      • 3、捕获信号后的三种处理方式
      • 4、对于自定义动作的捕获信号过程


一、信号的定义

信号在Linux中是一种软件中断,它提供了一种处理异步事件的方法。当某个事件发生时,操作系统会向目标进程发送一个信号。进程可以识别这个信号,并根据预设的处理方式做出相应的反应。

运行下面程序

int main()
{
    while(1);
    return 0;
}

在这里插入图片描述
观察上面,通过ctrl + c 就能结束进程,其实ctrl + c 就是一个信号,ctrl + c被操作系统解释然后向进程发送终止信号。

二、查看信号

1、通过 kill -l 指令可以查看信。
在这里插入图片描述

可靠信号:

  1. 又称之为RT信号或实时信号。 信号值位于SIGRTMIN(实时信号最小值)及SIGRTMAX(实时信号最大值)之间。
  2. 支持排队机制,确保多个信号能够被接收和处理,不会丢失。

非可靠信号:

  1. 信号值小于SIGRTMIN。
  2. 不支持排队机制,若一次性来了多个信号,这些信号不会排队,只会保留一个,后续的信号可能会被丢弃。

下面主要讨论的是1-31号信号

2、man 7 signal指令可以查看详细的信号信息。

在这里插入图片描述

TermCore的区别

一、Core(核心转储)

  1. 定义:当进程接收到某些信号(如SIGSEGV、SIGABRT等)时,如果操作系统配置了核心转储(CoreDump),那么进程当前的内存映像(包括代码、数据、堆栈等)会被写入到一个名为“core”的文件中。这个文件通常位于进程的当前工作目录下,文件名可能会附加进程的PID(进程标识符)以区分不同的核心转储文件。
  2. 目的:核心转储的主要目的是为了调试。当进程异常终止时,开发者可以通过分析核心转储文件来了解进程在终止时的状态,包括内存中的数据、堆栈信息等。这有助于定位问题的根源,并采取相应的修复措施。
  3. 触发条件:通常,只有当进程接收到某些特定的、与内存访问错误或程序异常终止相关的信号时,才会触发核心转储。这些信号的具体种类可能因系统而异,但通常包括SIGSEGV(段错误)、SIGABRT(异常终止)等。

通过ulimit命令查看操作系统是否开启Core
在这里插入图片描述
修改Core

ulimit -c 文件大小

产生core文件的条件
操作系统开启Core && 退出信号为Core

怎么查看退出信号是否为Core
在这里插入图片描述

开启Core后再执行下面程序后就会产生core文件

int test()
{
    int a = 10;
    //整数除零 -- 出异常 -- 信号:8
    int b = a / 0;
}

int main()
{
    pid_t id = fork();
    if(id == 0)
    {
        test();
    }
    else
    {
        int status = 0;
        waitpid(id,&status,0);
        //打印第8位
        std::cout<<((status>>7)&0x1)<<std::endl;
    }

    return 0;
}

二、Term(终止进程)

  1. 定义:当进程接收到某些信号(如SIGTERM、SIGINT等)时,操作系统会立即终止该进程的执行。这意味着进程的所有线程都将被停止,进程所占用的资源(如内存、文件描述符等)将被释放。
  2. 目的:终止进程的目的是为了释放系统资源,并确保系统的稳定性和安全性。当进程不再需要运行或其行为可能对系统造成危害时,操作系统会发送终止信号来停止该进程。
  3. 触发条件:触发终止信号的条件可能因信号而异。例如,SIGTERM信号通常用于请求进程正常退出,而SIGINT信号则通常用于中断当前正在运行的进程(如用户按下Ctrl+C时)。其他信号(如SIGKILL)则具有更高的优先级,可以立即终止进程而不给进程留下任何清理资源的机会。

三、产生信号

1、指令

kill -[信号]  [进程id]

如向进程 6666发送9号信号

kill -9 6666

2、系统调用

(1)kill函数
功能

先指定进程发送信号。

头文件

#include <sys/types.h>
#include <signal.h>

函数原型

int kill(pid_t pid, int sig);

参数

pid参数表示要终止的进程或线程的ID。
sig参数表示要发送的信号。

返回值

成功:返回0。
失败:返回-1。

(2) raise函数
功能

用于向当前进程发送一个指定的信号。

头文件

#include <signal.h>

函数原型

int raise(int signo);

参数

signo:要发送的信号编号。

返回值

成功:返回0。
失败:返回-1。

(3) abort函数
功能

用于异常终止当前程序的执行。当调用 abort函数时,程序会立即停止运行,并且会进行一系列的清理操作,包括刷新输出缓冲区(如果它们未被禁用)和生成一个核心转储文件(如果系统配置允许)。核心转储文件是一个包含程序终止时内存内容的文件,通常用于调试目的。

头文件

#include <stdlib.h>

函数原型

void abort(void);

3、由软件条件产生信号

当软件条件满足时,进程可以主动发送信号给自身或其他进程,以通知它们某些事件的发生或请求执行特定的操作。
alarm函数
功能

用于设置一个定时器,当定时器到期时,会向调用进程发送一个 SIGALRM 信号。这个函数通常用于实现简单的定时功能。

头文件

#include <unistd.h>

函数原型

unsigned int alarm(unsigned int seconds);

参数

seconds:定时器的时间长度,以秒为单位。如果 seconds 是0,那么任何当前已经设置的定时器都会被取消。

返回值

如果之前没有设置定时器,alarm 返回0。
如果之前已经设置了定时器,alarm 返回之前定时器剩余的时间(以秒为单位),即距离定时器到期还剩下的时间。

4、异常

如除0错误就会发送8号错误,使用野指针。

5、键盘输入

如ctrl + c 产生2号信号,ctrl + \ 产生3号信号。

四、保存信号

1、补充:信号其他相关概念

  1. 实际执行信号的处理动作称为信号递达(Delivery) 信号从产生到递达之间的状态,称为信号未决(Pending)。
  2. 进程可以选择阻塞 (Block )某个信号。 被阻塞的信号产生时将保持在未决状态,直到进程解除对此信号的阻塞,才执行递达的动作.
  3. 注意,阻塞和忽略是不同的,只要信号被阻塞就不会递达,而忽略是在递达之后可选的一种处理动作。

2、信号保存在哪,怎么保存?

保存task_struct结构体中,通过位图或者数组保存。
在这里插入图片描述

  1. 每个信号都有两个标志位分别表示阻塞(block)和未决(pending),还有一个函数指针表示处理动作。信号产生时,内核在进程控制块中设置该信号的未决标志,直到信号递达才清除该标志。
  2. 当接受到信号时会在合适时执行对应的函数。

3、信号集操作函数

(1)sigset_t

从上图来看,每个信号只有一个bit的未决标志,非0即1,不记录该信号产生了多少次,阻塞标志也是这样表示的。因此,未决和阻塞标志可以用相同的数据类型sigset_t来存储,sigset_t称为信号集,这个类型可以表示每个信号的“有效”或“无效”状态,在阻塞信号集中“有效”和“无效”的含义是该信号是否被阻塞,而在未决信号集中“有效”和“无效”的含义是该信号是否处于未决状态。下一节将详细介绍信号集的各种操作。阻塞信号集也叫做当前进程的信号屏蔽字(Signal Mask),这里的“屏蔽”应该理解为阻塞而不是忽略。

(2)处理sigset_t相关函数
头文件

#include <signal.h>

函数原型与功能

// 初始化信号集,使其不包含任何信号。
int sigemptyset(sigset_t *set);

//初始化信号集,使其包含所有可能的信号。
int sigfillset(sigset_t *set);

// 向信号集中添加指定的信号。
int sigaddset(sigset_t *set, int signum);

//从信号集中删除指定的信号。
int sigdelset(sigset_t *set, int signum);

//检查指定的信号是否属于信号集。
int sigismember(const sigset_t *set, int signum); 

参数

set:设置的信号集。
signum : 设置信号集的位置。

返回值

这四个函数都是成功返回0,出错返回-1。

(3)sigprocmask函数
功能

改变进程的当前阻塞信号集,或者检测当前进程的信号掩码的函数。

头文件

#include <signal.h>

函数原型

int sigprocmask(int how, const sigset_t *set, sigset_t *oldset);

参数

  1. how:指示如何修改当前信号屏蔽字。它可以是以下三个值之一: SIG_BLOCK:将 set 中指定的信号添加到当前进程的信号掩码中,即阻塞这些信号。 SIG_UNBLOCK:将 set 中指定的信号从当前进程的信号掩码中移除,即解除对这些信号的阻塞。 SIG_SETMASK:将当前进程的信号掩码设置为 set 中指定的信号掩码,即阻塞 set 中的信号,解除对其他信号的阻塞。
  2. set:指向一个信号集的指针,用于指定要阻塞或解除阻塞的信号。这个参数可以是 NULL,在这种情况下,how 参数的行为取决于是否要获取当前的信号屏蔽字(通过 oldset 参数)(输入型参数)。
  3. oldset:指向一个信号集的指针,用于保存之前的信号掩码。如果 oldset 不是 NULL 指针,那么当前的信号屏蔽字会由此指针返回。如果 oldset 是 NULL,则不保存旧的信号屏蔽字(输出型参数)。

返回值

  1. 如果 sigprocmask 执行成功,则返回 0。
  2. 如果执行失败,则返回 -1,并设置 errno 以指示错误。

使用
将2号信号阻塞。

int main()
{
    //信号集
    sigset_t set, oldset;

    // 初始化
    sigemptyset(&set);
    sigaddset(&set, 2);

    // 设置阻塞
    sigprocmask(SIG_BLOCK, &set, &oldset);

    //循环,让程序不要结束
    while (1);
    return 0;
}

现象:ctrl + c 不能终止进程了,说明2号信号被阻塞了。
在这里插入图片描述
(4)sigpending函数
功能

于获取当前阻塞信号集。

头文件

#include <signal.h>

函数原型

int sigpending(sigset_t *set);

参数

set:这是一个指向 sigset_t 类型的指针,用于存储当前被阻塞的信号集。sigset_t 是一个数据类型,用于表示信号集(输出型参数)。

返回值

成功时,sigpending 返回 0。
失败时,返回 -1,并设置 errno 以指示错误原因。

五、捕获信号

1、概念

进程捕获信号的过程,即进程在接收到信号后,根据信号的编号和预设的处理函数进行相应的处理。

2、捕获信号的时机

进程在接收到信号后,并不是立即处理信号,而是在合适的时候进行处理。这个合适的时候通常指的是进程从内核态切换回用户态过程中。当进程处于内核态时,它无法直接处理用户空间的信号。因此,当进程从内核态返回用户态时,操作系统会检查进程是否有未处理的信号,如果有,则根据信号的编号和预设的处理函数进行相应的处理。

3、捕获信号后的三种处理方式

(1)默认处理

使用内置的处理函数。

(2)自定义和忽略

自定义:用户自定义。
忽略:递达后不做处理。

signal函数
功能

头文件

#include <signal.h>

函数原型

typedef void (*sighandler_t)(int);	//int 参数 为触发信号的编号
sighandler_t signal(int signum, sighandler_t handler);

参数

  1. signum:指定要处理的信号编号。例如,SIGINT(中断信号,通常由 Ctrl+C 产生)、SIGTERM(终止信号)等。
  2. handler:指定信号处理程序,它是一个返回类型为 void 并接受一个 int 参数的函数指针。如果传递 SIG_IGN,则忽略该信号;如果传递 SIG_DFL,则使用默认的信号处理行为。

返回值

signal 函数返回之前设置的信号处理程序(如果有的话),如果出现错误则返回 SIG_ERR。

使用

void sigcb(int signum)
{
    std::cout << "signum : " << signum << std::endl;
}

int main()
{
    //改变信号 2 - ctrl + c
    signal(2,sigcb);

    //signal(2,SIG_IGN);  //忽略信号
   // signal(2,SIG_DFL);//使用默认处理方法 :注意:不调用函数也是使用默认的方法
    
    //别让程序结束
    while(1);

    return 0;
}

现象:
当传递2号信号时不再终止程序,而是执行我们传入的函数。
在这里插入图片描述
本质:通过signal函数修改handler数组的函数指针。

sigaction函数
功能

sigaction 函数是 POSIX 标准中用于设置信号处理程序的函数,它提供了比 signal 函数更强大和灵活的功能。sigaction 允许你详细指定信号处理的各个方面,包括信号处理程序、信号屏蔽集和标志。

头文件

#include <signal.h>

函数原型

struct sigaction {
    void (*sa_handler)(int);      // 或者使用 sa_sigaction
    void (*sa_sigaction)(int, siginfo_t *, void *);
    sigset_t sa_mask;             // 调用处理程序时要阻塞的信号集
    int sa_flags;                 // 标志位,控制行为的选项
    void (*sa_restorer)(void);    // 已废弃,不应使用
};
/*
sa_handler 或 sa_sigaction:指定信号处理程序。sa_handler 是一个简单的函数指针,而 sa_sigaction 提供了一个更复杂的接口,允许访问更多关于信号的信息。
sa_mask:在调用信号处理程序时,要阻塞的信号集。这可以防止在信号处理程序运行时接收到其他信号。
sa_flags:标志位,用于控制 sigaction 的行为。常用的标志包括 SA_RESTART(如果信号处理程序被中断的系统调用应该自动重启)、SA_SIGINFO(使用 sa_sigaction 而不是 sa_handler)等。
sa_restorer:这是一个已废弃的字段,不应在新代码中使用。
*/
int sigaction(int signum, const struct sigaction *act, struct sigaction *oldact);

参数

  1. signum:指定要处理的信号编号。
  2. act:指向一个 struct sigaction 结构的指针,该结构包含了新的信号处理程序的设置。
  3. oldact:如果 oldact 不为 NULL,则 sigaction 函数会将之前的信号处理设置存储在这个指向 struct
    sigaction 结构的指针中。

返回值

如果 sigaction 成功,则返回 0。
如果失败,则返回 -1,并设置 errno 以指示错误。

使用


void sigcb(int signum)
{
    std::cout << "signum : " << signum << std::endl;
}

int main()
{
    struct sigaction act,oldact;

    //初始化
    sigemptyset(&act.sa_mask);
    act.sa_handler = sigcb;

    //act - 输入型参数  oldact - 输出型参数
    sigaction(2, &act, &oldact);

    while(1);

    return 0;
}

4、对于自定义动作的捕获信号过程

在这里插入图片描述

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

如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈,一经查实,立即删除!

相关文章

group_concat配置影响程序出bug

在 ThinkPHP 5 中&#xff0c;想要临时修改 MySQL 数据库的 group_concat_max_len 参数&#xff0c;可以使用 原生 SQL 执行 来修改该值。你可以通过 Db 类来执行 SQL 语句&#xff0c;从而修改会话&#xff08;Session&#xff09;级别的变量。 步骤 设置 group_concat_max_l…

云专线优势有哪些?对接入网络有什么要求?

云专线是一种连接企业本地数据中心与云服务提供商之间的专用网络连接方式&#xff0c;具有以下优势&#xff1a; 高安全性&#xff1a;云专线提供了物理隔离的数据传输通道&#xff0c;减少了数据在公共互联网上传输时可能遭遇的安全风险。 低延迟&#xff1a;由于是直接连接&a…

【提高篇】3.1 GPIO(二,结构与工作模式介绍)

目录 一,GPIO的基本结构 1.1 保护二极管 1.2 上拉、下拉电阻 1.3 施密特触发器 1.4 P-MOS 管和 N-MOS 管 P-MOS管和N-MOS管的区别 1.5 片上外设 1.6 IDR,ODR,BSRR寄存器 1.6.1 IDR(Input Data Register) 1.6.2 ODR(Output Data Register) 1.6.3 BSRR(Bit Se…

数据迁移: 安全高效转移数据, 满足企业业务需求和技术改进

天津鸿萌科贸发展有限公司从事数据安全服务二十余年&#xff0c;致力于为各领域客户提供专业的数据存储、数据恢复、数据备份、数据迁移等解决方案与服务&#xff0c;并针对企业面临的数据安全风险&#xff0c;提供专业的相关数据安全培训。 鸿萌数据迁移业务为众多企业顺利高效…

Am I Isolated:一款安全态势基准测试工具

基于Rust的容器运行时扫描器作为一个容器运行&#xff0c;检测用户容器运行时隔离中的漏洞。 它还提供指导&#xff0c;帮助用户改善运行时环境&#xff0c;以提供更强的隔离保证。 容器的现状是它们并不包含&#xff08;隔离&#xff09;。 容器隔离的缺失在云原生环境中有…

战略共赢 软硬兼备|云途半导体与知从科技达成战略合作

2024年11月5日&#xff0c;江苏云途半导体有限公司&#xff08;以下简称“云途”或“云途半导体”&#xff09;与上海知从科技有限公司&#xff08;以下简称“知从科技”&#xff09;达成战略合作&#xff0c;共同推动智能汽车领域高端汽车电子应用的开发。 云途半导体与知从科…

基于卷积神经网络的农作物病虫害识别系统(pytorch框架,python源码)

更多图像分类、图像识别、目标检测等项目可从主页查看 功能演示&#xff1a; 基于卷积神经网络的农作物病虫害检测&#xff08;pytorch框架&#xff09;_哔哩哔哩_bilibili &#xff08;一&#xff09;简介 基于卷积神经网络的农作物病虫害识别系统是在pytorch框架下实现的…

2-149 基于matlab的LDPC译码性能分析

基于matlab的LDPC译码性能分析&#xff0c;LDPC&#xff08;Low-Density Parity-Check&#xff09;码作为编码技术&#xff0c;具有优秀的纠错性能和较低的编解码复杂度。为保证可靠的数据传输&#xff0c;对传输过程中可能出现的信道噪声、干扰等进行模拟和分析。分析对比了误…

算法每日双题精讲——双指针(快乐数,盛最多水的容器)

&#x1f31f;快来参与讨论&#x1f4ac;&#xff0c;点赞&#x1f44d;、收藏⭐、分享&#x1f4e4;&#xff0c;共创活力社区。 &#x1f31f; 别再犹豫了&#xff01;快来订阅我们的算法每日双题精讲专栏&#xff0c;一起踏上算法学习的精彩之旅吧&#xff01;&#x1f4aa;…

在Scrapy爬虫中应用Crawlera进行反爬虫策略

在互联网时代&#xff0c;数据成为了企业竞争的关键资源。然而&#xff0c;许多网站为了保护自身数据&#xff0c;会采取各种反爬虫技术来阻止爬虫的访问。Scrapy作为一个强大的爬虫框架&#xff0c;虽然能够高效地抓取网页数据&#xff0c;但在面对复杂的反爬虫机制时&#xf…

Linux(CentOS)安装 JDK

CentOS版本&#xff1a;CentOS 7 JDK版本&#xff1a;JDK17 1、下载 JDK 官网&#xff1a;https://www.oracle.com/ 2、上传 JDK 文件到 CentOS 使用FinalShell远程登录工具&#xff0c;并且使用 root 用户连接登录&#xff08;注意这里说的root用户连接登录是指这样的&…

redis和数据库的数据一致性

在我们使用redis作为缓存的时候&#xff0c;数据库和缓存数据保持一致性就显得尤为重要&#xff0c;因为如果不做处理的话很有可能读取到的数据会出现差错&#xff0c;那这里怎么进行解决呢&#xff1f; 首先我们先来看一下操作数据到底是直接删除数据还是说通过修改的方式来修…

发布 VectorTraits v3.0(支持 X86架构的Avx512系列指令集,支持 Wasm架构及PackedSimd指令集等)

文章目录 支持 X86架构的Avx512系列指令集支持Avx512时的输出信息 支持 Wasm架构及PackedSimd指令集支持PackedSimd时的输出信息VectorTraits.Benchmarks.Wasm 使用说明 新增了向量方法支持 .NET 8.0 新增的向量方法提供交织与解交织的向量方法YGroup3Unzip的范例代码 提供重新…

工业相机常用功能之白平衡及C++代码分享

目录 1、白平衡的概念解析 2、相机白平衡参数及操作 2.1 相机白平衡参数 2.2 自动白平衡操作 2.3 手动白平衡操作流程 3、C++ 代码从XML读取参数及设置相机参数 3.1 读取XML 3.2 C++代码,从XML读取参数 3.3 给相机设置参数 1、白平衡的概念解析 白平衡(White Balance)…

推荐一款SSD硬盘优化器:Auslogics SSD Optimizer Pro

SSD Optimizer Pro 是一款专为优化固态硬盘 (SSD) 性能而设计的专业工具&#xff0c;旨在最大化 SSD 的效率&#xff0c;延长硬盘使用寿命。凭借简便的操作界面和强大的优化功能&#xff0c;SSD Optimizer Pro 可以让用户充分利用 SSD 的优势&#xff0c;从而获得更高的系统性能…

常用机器人算法原理介绍

一、引言 随着科技的不断发展&#xff0c;机器人技术在各个领域得到了广泛应用。机器人算法是机器人实现各种功能的核心&#xff0c;它决定了机器人的行为和性能。本文将介绍几种常用的机器人算法原理&#xff0c;包括路径规划算法、定位算法和运动控制算法。 二、路径规划算法…

基于开源 AI 智能名片 S2B2C 商城小程序的视频号交易小程序优化研究

摘要&#xff1a;本文探讨了完善适配视频号交易小程序的重要意义&#xff0c;重点阐述了开源 AI 智能名片 S2B2C 商城小程序在这一过程中的应用。通过分析其与直播间和社群的无缝衔接特点&#xff0c;以及满足新流量结构下基础设施需求的能力&#xff0c;为门店在视频号直播交易…

【OH】openHarmony开发环境搭建(基于windows子系统WSL)

前言 本文主要介绍基于windows子系统WSL搭建openHarmony开发环境。 WSL与Vmware虚拟机的区别&#xff0c;可以查看WSL与虚拟机的区别 更详细的安装配置过程可参考微软官网&#xff1a; ​安装 WSL 前提 以下基于windows 111专业版进行配置&#xff0c;windows 10应该也是可以…

WPF使用Prism框架首页界面

1. 首先确保已经下载了NuGet包MaterialDesignThemes 2.我们通过包的项目URL可以跳转到Github上查看源码 3.找到首页所在的代码位置 4.将代码复制下来&#xff0c;删除掉自己不需要的东西&#xff0c;最终如下 <materialDesign:DialogHostDialogTheme"Inherit"Ide…

AHB Matrix 四星级 验证笔记(2.4) Tt3.3AHB总线协议测试时的 并行数据

文章目录 前言一、代码二、错误1.地址范围2. 并行执行线程中变量覆盖的情况3.有关incr的beat 前言 来源路科验证本节搞定 T3.3 AHB总线协议的覆盖&#xff1a;AHB_PROTOCOL_COVER 即测试ahb slave接口和master接口支持&#xff08;尽可能&#xff09;全部的ahb协议传输场景&am…