目录

  • 1. 进程的异常终止与core dump标志位
    • 1.1 进程终止的方式
    • 1.2 core方案的作用与使用方式
  • 2. 信号的保存
    • 2.1 信号的阻塞
    • 2.2 操作系统中的sigset_t信号集类型
    • 2.3 进程PCB中修改block表的系统调用接口
    • 2.4 信号阻塞的相关问题验证

1. 进程的异常终止与core dump标志位

1.1 进程终止的方式

  进程的终止方式大体可以分为两种,正常终止异常终止。这两种进程终止方式的不同会表现在进程的退出码上,进程终止退出时会返回一个int类型的变量。此变量中只有低16bit位会被利用起来存储信息,具体存储方式如下:
在这里插入图片描述
  当进程正常结束,进程的退出码会写在次低8bit位(16 ~ 8之间)的范围中(下标从0开始),退出码会表示进程退出的状态。而当进程被信号终止,异常退出时,退出码的低7bit位(7 ~ 0之间)的范围内会写入进程收到的信号。

  而信号异常终止的情况又被分为两种,分别为Term方案与Core方案处理:

  • term方案(termination): 直接退出,然后进程释放其的占用的资源
  • core方案: 被称之为核心转储,将核心信息转移储存到生成的Core文件中,此文件存储着进程异常终止的错误信息(发生了什么错误,导致错误发生的代码是哪一行),便于后续排查错误。
      哪种信号导致的进程终止会使用哪个方案,可使用指令man 7 signal浏览手册,查看具体信息。
    在这里插入图片描述
      退出码的第8个bit位,则是表示此进程的退出是否为core退出,值为1表示是,值为0表示否。当core方案默认没有打开时,core退出的信号最后的退出方式也是term,core dumped位为0。

观察异常退出进行的退出码:

//打开core方案
int main()
{pid_t pid = fork();if(pid == 0){int a = 10;a /= 0;exit(0);}int status = 0;pid_t rid = waitpid(pid, &status, 0);if(rid ==  pid){cout << "exit code : " << ((status >> 8) & 0xFF) << endl;//退出码 0cout << "exit signal : " << ((status) & 0x7F) << endl;	 //退出信号 SIGFPE : 8cout << "core dump : " << ((status >> 7) & 0x1) << endl; //core dump位 1cout << "status : " << status << endl;}return 0;
}

1.2 core方案的作用与使用方式


以下进行试验与得出的结论都是基于Ubuntu 20.04 LTS系统版本
在这里插入图片描述

core模式的打开与关闭:
  云服务器中,core模式是被默认关闭的,在想要使用core退出之前,需要先将core模式打开。当前进行的版本中,必须先执行sudo bash -c "echo core.%p > /proc/sys/kernel/core_pattern"指令,后续才能打开core模式。

  • 指令ulimit -a 查看core方案是否打开
    在这里插入图片描述
  • 指令ulimit -c file-size 设置core文件的大小,当core文件大小不为0时,core模式就被打开了。旧版内核中,只有root用户才能够执行此条命令,而新版本内核中则没有此限制
    在这里插入图片描述
  • 指令ulimit -c 0 将core文件的大小设置为0时,core模式就会被关闭

core退出后core文件的使用方式:
  当进程因为收到core方案退出的信号而终止后,会打印出错误类型,错误信息后带注释信息(core dumped)。然后会生成一个core文件,core文件一般会有两种,core文件或core.pid文件。
在这里插入图片描述
  当进程core方案退出后,生成了对应的core文件后,我们就可以在Linux下的gdb调试工具中,通过core-file core/core.pid的方式,查看core文件中的异常错误信息。此种core文件协助调试的方式,被称之为事后调试

在这里插入图片描述


云服务器默认与重启后关闭core退出的原因:
  云服务器一般都是会一直运行的,以此来持续给客户端提供各种服务。当然,在此过程中会有程序异常中断的可能。

    1. 但因为一些服务程序的重要性,不能使其因为中断就一直停止运行。
    1. 所以,云服务器上的重要服务异常中断时,会使用软件方式让其自动重启,以求让其能够正常给大部分客户端提供服务。
    1. 可若是云服务器默认打开了core异常退出方案的设置,在不断重启程序的过程中,就会导致生成大量的core.pid文件,最后就会使得服务器的磁盘被打满服务器最后整个崩溃

  在版本的较新的内核中,会将core方案退出生成的文件都命名为core。这样即使服务不断重启,每次生成的core文件也只会不断覆盖,core文件始终只存在一份。服务器也就不会因此而导致崩溃。

2. 信号的保存


概念补充:

  • 信号被进程接收后进行处理,信号的处理也被称之为信号递达
  • 信号从产生到递达之间的状态,被称为信号未决

2.1 信号的阻塞

1. 信号阻塞的概念:
  操作系统中,进程可以选择对指定的信号进行阻塞,也可以称之为屏蔽。被阻塞的信号,即使被进程接收保存,也不会被进程处理。如果一个信号被阻塞,则该信号永远也不会被递达,除非进程对指定信号解除阻塞。进程PCB中存在着一个变量int block,此变量实际上是一张位图,此位图中的bit位都代指着一种信号,bit位的位置表示信号的编号,bit位的内容则是标识着进程对此信号是否屏蔽若bit位的值是1,则表示进行了屏蔽,若值是0,则表示没有进行屏蔽
  对应信号的处理方法,在进程PCB中也有对应的一个函数指针数组handler_t* handler做存储与管理。再综合之前信号产生中的知识,进程存储信号的pending位图。可以得知,操作系统中,进程PCB对于信号的阻塞、保存、处理分别都有一张表用于描述与管理。
在这里插入图片描述
2. 信号的忽略与阻塞:
  信号的阻塞与忽略并不是一种行为,对信号进行阻塞,进程是无法识别到有对应的信号到了,所以也就不会做出响应处理。而信号的忽略,则是进程已经识别到了信号,但对信号采用了忽略这一处理方式,所以,表现出的现象就是进程什么都没有做。总而言之,阻塞就是进程没有识别到信号,而忽略则是进程识别到了但什么都不做。
  当信号被阻塞屏蔽时,此种信号在一段时间内大量的被发送给此进程。对于普通信号pending表中只会存储一个,在接触阻塞之后,进程只会对最近的一次信号做处理。而对于实时信号,在递达之前同种信号产生多次,则是会依次放在一个队列里,此处不做详细讨论。

2.2 操作系统中的sigset_t信号集类型

  操作系统中,用户是不能对系统的内核资源直接做修改的,只能通过操作系统提供系统调用接口来间接达成修改的目的。block信号阻塞表就属于操作系统的内核资源,操作系统对此提供了专用的用户级数据类型sigset_t与系统调用接口。sigset_t也被称为信号集
  此类型为操作系统提供的位图类型,创建一个此类型变量修改其中内容并配合相应的系统调用接口就可以达到对block表的修改,即控制进程阻塞哪些信号。此外,sigset_t类型同样可以用于接收pending表中的内容,以此来达到让用户查看pending的目的。sigset_t类型相关的系统调用接口具体如下:

  • 1. 将sigset_t变量内容置0
#include <signal.h>
int sigemptyset(sigset_t* set);
  • 2. 将所有bit位都设置为1(用于阻塞所有信号)
int sigfillset(sigset_t* set);
  • 3. 将指定bit位设置为1(用于阻塞指定信号)
int sigaddset(sigset_t* set, int signo);
  • 4. 将指定bit位设置为0(用于解除阻塞信号)
int sigdelset(sigset_t* set, int signo);
  • 5. 用于查看信号集中是否存在某个信号(配合查看pending表)
int sigismember(const sigset_t* set, int signo);

2.3 进程PCB中修改block表的系统调用接口

#include <signal.h>//signal mask信号屏蔽字
int sigprocmask(int how, const sigset_t* set, sigset_t* oldset);
  • 参数1int how 系统内置宏参数,用于指定调用接口的模式
宏常量作用
SIG_BLOCK将 set 中的信号添加到当前信号屏蔽字中(阻塞这些信号)
SIG_UNBLOCK将 set 中的信号从当前信号屏蔽字中移除(解除阻塞)
SIG_SETMASK将当前信号屏蔽字直接设置为 set(完全覆盖)
  • 参数2const sigset_t* set block表修改的新参考信号集
  • 参数3sigset_t* oldset 被修改前的就信号集

  sigset_t信号集在不同平台下的实现方式不同,此系统内置类型不支持cout流插入或printf直接打印。sigset_t信号集被定义与修改好后,并没有直接达到修改block表的效果,需要配合sigprocmask接口才能真的将数据设置进内核。

2.4 信号阻塞的相关问题验证

  • 问题1:如果一个进程将所有信号都进行屏蔽,那么这个进程是否就无法被外部终止了

  验证方式: 创建一个死循环的进程,使用系统调用接口让此进程屏蔽所有信号,最后让其运行起来。待其运行之后,再使用指令对此进程尝试一个一个发出所有信号,观察进程反应。进程运行时,可以循环打印自己的pending表,当表bit位为1时,表示着进程收到了信号,但信号并没有被处理,这代表信号成功被阻塞。

实验代码:

void PrintPending()
{sigset_t sig;sigemptyset(&sig);sigpending(&sig);for(int i = 31; i > 0; i--){if(sigismember(&sig, i)){cout << "1";}else{cout << "0";}}cout << " , pid is : " << getpid() << endl;
}int main()
{sigset_t sig;sigemptyset(&sig);for(int i = 1; i <= 31; i++)sigaddset(&sig, i);int n = sigprocmask(SIG_SETMASK, &sig, nullptr);assert(n == 0);(void)n;//如此强转,是因为在release版本下,变量n后续若是没有使用编译器会报警cout << "signal mask success..." << endl;while(true){PrintPending();sleep(1);}return 0;
}

验证结果:
  进程运行后,使用指令c=1; while [ $c -le 31 ]; do kill -$c pid; echo kill -$c; let c++; sleep 1; done发送信号,观察现象。
在这里插入图片描述
  运行程序执行指令后,可以发现,9号信号被发送后成功递达,SIGKILL:9号信号并不能被屏蔽。
在这里插入图片描述
  跳过9号信号之后继续验证其他信号,由运行结果发现SIGSTOP:19号信号也没有被屏蔽。而18号信号虽然能够正常屏蔽,但屏蔽18号信号之后又会导致一些已经被屏蔽的信号接触阻塞。
  操作系统如此设置的原因,是为了预防出现非法的病毒进程将自己的所有信号都设置阻塞,导致操作系统无法杀死病毒进程。


问题2:操作系统中进程在进行递达操作时,是先将pending表中的信号bit位清0,还是先执行handler处理函数

  验证方法: 自定义一个信号的递达处理函数handler,让其在handler函数查看当前进程的pending表中的对应信号bit位。若pending表中的对应信号bit位清0了,代表清0操作于handler方法之前执行,若bit位置未清0,则代表清0操作于handler方法之后。

验证代码:

void handler(int signo)
{sigset_t sig;sigemptyset(&sig);sigpending(&sig);if(sigismember(&sig, signo)){cout << "先执行handler" << endl;}else{cout << "先清0" << endl;}
}int main()
{signal(SIGINT, handler);while(true){cout << "process pid is : " << getpid() << endl;sleep(1);}return 0;
}

验证结果:先清0
在这里插入图片描述

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

如若内容造成侵权/违法违规/事实不符,请联系英文站点网进行投诉反馈email:809451989@qq.com,一经查实,立即删除!

相关文章

数据分析编程第二步: 最简单的数据分析尝试

2.1 数据介绍有某公司的销售数据表 sales.csv 如下:第一行是标题&#xff0c;解释每一列存了什么东西。第二行开始每一行是一条数据&#xff0c;对应一个订单。这种数据有个专业的术语&#xff0c;叫结构化数据。这是现代数据处理中最常见的数据类型。整个表格的数据统称为一个…

UDP报文的数据结构

主要内容参照https://doc.embedfire.com/net/lwip/zh/latest/doc/chapter14/chapter14.html#id6&#xff0c;整理出来自用。 1. UDP 报文首部结构体&#xff08;udp_hdr&#xff09; 为清晰定义 UDP 报文首部的各个字段&#xff0c;LwIP 设计了udp_hdr结构体&#xff0c;其包含…

图论与最短路学习笔记

图论与最短路在数学建模中的应用 一、图论模型图 G(V,E)G(V,E)G(V,E) VVV&#xff1a;顶点集合EEE&#xff1a;边集合每条边 (u,v)(u,v)(u,v) 赋予权值 w(u,v)w(u,v)w(u,v)&#xff0c;可用 邻接矩阵 或 邻接表 表示。二、最短路问题的数学形式 目标&#xff1a;寻找从源点 sss…

第九节 Spring 基于构造函数的依赖注入

当容器调用带有一组参数的类构造函数时&#xff0c;基于构造函数的 DI 就完成了&#xff0c;其中每个参数代表一个对其他类的依赖。接下来&#xff0c;我们将通过示例来理解 Spring 基于构造函数的依赖注入。示例&#xff1a;下面的例子显示了一个类 TextEditor&#xff0c;只能…

【数据库】PostgreSQL详解:企业级关系型数据库

文章目录什么是PostgreSQL&#xff1f;核心特性1. 标准兼容性2. 扩展性3. 高级功能4. 可靠性数据类型1. 基本数据类型2. 高级数据类型基本操作1. 数据库操作2. 表操作3. 数据操作高级查询1. 连接查询2. 子查询3. 窗口函数JSON操作1. JSON数据类型2. JSON查询3. JSON索引全文搜索…

FFMPEG相关解密,打水印,合并,推流,

1&#xff1a;ffmepg进行打水印解密 前提ffmepg安装利用静态版就可以这个什么都有&#xff0c;不用再配置其他信息&#xff1a;&#xff08;这个利用ffmpeg终端命令是没问题的&#xff0c;但是如果要是再C中调用ffmpeg库那么还需要从新编译安装下&#xff09; 各个版本 Inde…

MySql知识梳理之DML语句

注意: 插入数据时&#xff0c;指定的字段顺序需要与值的顺序是一一对应的。 字符串和日期型数据应该包含在引号中。 插入的数据大小&#xff0c;应该在字段的规定范围内注意:修改语句的条件可以有&#xff0c;也可以没有&#xff0c;如果没有条件&#xff0c;则会修改整张表的所…

GaussDB GaussDB 数据库架构师修炼(十八)SQL引擎-SQL执行流程

1 SQL执行流程查询解析&#xff1a;词法分析、语法分析、 语义分析 查询重写&#xff1a;视图和规则展开、基于规则的查询优化 计划生成&#xff1a;路径搜索和枚举、选出最优执行计划 查询执行&#xff1a;基于优化器生成的物理执行计划对数据进行获取和计算2 解析器和优化器S…

grpc 1.45.2 在ubuntu中的编译

要在 Ubuntu 上编译 gRPC 1.45.2&#xff0c;需要按照以下步骤操作。以下指南基于 gRPC 官方文档和相关资源&#xff0c;确保环境配置正确并成功编译。请确保你有管理员权限&#xff08;sudo&#xff09;以安装依赖项和执行相关命令。 1. 准备环境 确保你的 Ubuntu 系统已安装…

lesson45:Linux基础入门指南:从内核到实践操作全解析

目录 一、Linux简介与核心概念 1.1 Linux的起源与发展 1.2 内核与发行版的关系 二、Linux内核版本解析 2.1 内核版本命名规则 2.2 2025年主流内核版本 三、主流Linux发行版对比 3.1 桌面用户首选 Ubuntu 24.04 LTS Linux Mint 22 3.2 技术爱好者之选 Fedora 41 Ar…

PCL点云库入门(第24讲)——PCL库点云特征之NARF特征描述 Normal Aligned Radial Feature(NARF)

一、算法原理 1、NARF 特征概述 NARF(Normal Aligned Radial Feature)是 2011 年由 Bastian Steder 等人在论文 《Point Feature Extraction on 3D Range Scans Taking into Account Object Boundaries》中提出的一种 稀疏局部 3D 特征描述子。 核心目标是提取具有“边界意…

使用 eventpp 构建跨 RT-Thread 与 ARM-Linux 的轻量级 Active Object(AO)事件驱动框架

0. 引言 本文展示一个实践路径&#xff1a;以轻量级 C 事件库 eventpp 为核心&#xff0c;设计并实现一个面向嵌入式的、可移植的 Active Object&#xff08;AO&#xff09;事件驱动架构。该架构满足以下目标&#xff1a; 跨平台兼容&#xff1a;单套代码在 RT-Thread&#xff…

【python实用小脚本-193】Python全能PDF小助手:剪切/合并/旋转/加密一条龙——再也不用开会员

Python全能PDF小助手&#xff1a;剪切/合并/旋转/加密一条龙——再也不用开会员 PDF编辑, 本地处理, 零会员费, 多功能脚本, 瑞士军刀 故事开场&#xff1a;一把瑞士军刀救了周五下班的你 周五 17:55&#xff0c;老板甩来一堆 PDF&#xff1a; “把第 3、7 页删掉”“再和合同合…

Ubuntu根分区扩容

目录 1.先查看/dev/sda 整块磁盘设备的分区占用情况&#xff1a; 2.在VMware中编辑虚拟机&#xff1a; 3.进入虚拟机&#xff0c;进入disk应用程序&#xff1a; 4.扩容文件系统 5.最后通过df-h lsblk或通过可视化GParted进行验证。 1.先查看/dev/sda 整块磁盘设备的分区占…

智慧城市SaaS平台/市政设施运行监测系统之空气质量监测系统、VOC气体监测系统、污水水质监测系统及环卫车辆定位调度系统架构内容

1. 空气质量监测系统1) 监测点管理 a) 监测点基本信息 支持记录空气质量监测点的名称、位置、类型、设备配置等信息。 b) 监测点分布地图 支持通过GIS地图展示监测点的分布情况&#xff0c;支持地图查询和导航。 2) 空气质量监测 a) 实时数据采集 支持实时采集空气质量数据&…

PiscCode迅速集成YOLO-Pose 实现姿态关键点轨迹跟踪应用

在计算机视觉领域&#xff0c;人体姿态检测与轨迹跟踪是很多应用场景的核心技术&#xff0c;例如运动分析、行为识别、智能监控等。本文将介绍如何在 PiscCode 平台上&#xff0c;利用 YOLO-Pose 模型进行姿态估计&#xff0c;并实现多人关键点轨迹跟踪。 一、什么是 PiscCode …

HTTP的状态码有哪些,并用例子说明一下

问题HTTP的状态码有哪些&#xff0c;并用例子说明一下我的回答HTTP状态码是服务器对客户端请求的响应码&#xff0c;它们按照不同的功能被分为五大类。我来介绍一下主要的状态码及其实际应用场景&#xff1a;1xx&#xff08;信息性状态码&#xff09;&#xff1a;表示请求已接收…

【51单片机】【protues仿真】基于51单片机宠物投食器系统

目录 一、主要功能 二、使用步骤 三、硬件资源 四、软件设计 五、实验现象 一、主要功能 1、LCD1602液晶显示当前时间 2、按键设置时间&#xff0c;5个定时投喂时间​ 3、可以通过手动按键进行投喂食物 4、步进电机模拟投喂食物 二、使用步骤 基于51单片机的宠物自动投…

掌握设计模式--命令模式

命令模式&#xff08;Command Pattern&#xff09; 命令模式&#xff08;Command Pattern&#xff09;是一种行为型设计模式&#xff0c;它将请求&#xff08;命令&#xff09;封装成对象&#xff0c;从而使您能够参数化客户端&#xff08;调用者&#xff09;使用不同的请求、…

STM32之beep、多文件、延迟、按键以及呼吸灯

一、Beep控制 原理图分析&#xff1a; 蜂鸣器三极管控制引脚对应 MCU PB8。当前蜂鸣器对应的电路中&#xff0c;三极管是 NPN 三极管&#xff0c;当前【基极】存在小电流&#xff0c;当前三极管导通。要求对应 PB8 引脚对外输出电压 / 电流。当前 PB8 输出高电平&#xff0c;当…