Linux——进程信号1

news2025/1/10 20:58:56

信号和信号量是俩个东西,俩者无关系。

信号

信号本质是一种通知机制,用户or操作系统通过发送一定的信号,通知进程,某些事件已经发送,让进程进行后续处理。

结合进程,信号结论:

  1. 进程要处理信号,进程必须具备识别信号的能力。

  1. 凭什么进程能够识别信号呢?程序员让进程具备了识别信号的能力

  1. 信号是随机产生的,进程可能正在忙自己的事情,所以,信号的后续处理可能不是立即处理的

  1. 信号会被临时记录下来,方便后续处理

  1. 什么时候处理呢?合适的时候。

  1. 一般而言信号的产生,相对于进程而言是异步的(信号和进程各干各的,互不影响)。

信号如何产生

我们写一个死循环程序,按ctrl+c可直接退出

这是因为ctrl+c:本质是向进程发送二号信号,我们输入kill -2 PID值,效果跟ctrl+c一样

下图都是信号,左侧是信号编号,右侧是宏值

处理信号的方式

  1. 默认(进程自带的,程序员写好的逻辑)

  1. 忽略(也是信号处理的一种方式)

  1. 自定义动作(捕捉信号)

常见信号(kill -l可查看所有信号)

【1,31】是普通信号,后面的是实时信号,实时信号对信号处理要求比较高

也可输入man 7 signal,可查看信号的详细描述

如何理解组合键变成信号呢?

键盘的工作方式是通过中断方式进行的,操作系统可以识别组合键

如何理解信号被进程保存呢?

  1. 什么信号?

  1. 是否产生?

进程必须要有保存信号的相关数据结构(位图,unsigned int,用比特位的位置表示信号),PCB内部保存了信号位图字段

信号发送本质:信号位图是在task_struct内核数据结构中,只有操作系统去发送信号,即信号发送的本质:OS向目标进程写信号,OS直接修改PCB中指定的位图结构,完成“发送”信号的过程。

OS解释组合键->查找进程列表->前台运行的进程->OS写入对应的信号到进程内部的位图结构中

产生信号的方式

1. 通过终端按键产生信号

signal函数,作用:对特定的信号进行捕捉,这种方式属于自定义捕捉

第一个参数是要捕捉的信号,可传入[1,31]对应的数字,也可传入对应的字母如SIGINT

typedef void (*sighandler_t)(int) 是一个函数指针,因此第二个参数时一个函数指针

signal通过回调的方式,修改对应的信号捕捉方法。

返回值也是个函数指针,一般不需要关心返回值,当我们捕捉了一个新的方法时,该函数会返回老的方法

catchSig的参数含义是:将信号对应的编号以参数形式传到这里

运行程序后,我们ctrl+c,此时会捕捉到信号,但是程序还在运行,ctrl+c未能让进程终止

这是因为以前2号信号处理动作默认是终止进程,而现在我们把二号信号的处理动作给改了(改成了打印一句话),因此对应的进程就不再退出。

signal函数仅仅是修改进程对特定信号的后续处理动作,不是直接调用对应的处理动作。即:如果后续没有任何SIGINT信号产生,catchSig永远也不会被调用

就好比新颁布了一项法律,若没人触犯该法,该条法律则永远不会被使用。

信号也是如此,我们只是提前注册了一个捕捉到信号的方法,若后续未捕捉到信号,则不会使用该方法。

特定信号的处理动作一般只有一个。

我们此时发送别的信号,可使程序退出如ctrl+\,这其实是3号信号

我们对2号和3号信号使用同一个捕捉方法

再次运行

用kill发送信号

我们发送8号信号,可终止程序,8号信号是浮点数异常

man 7 signal,我们可以看到3号信号后面是Core

Core核心转储

在进程等待部分,当进程退出时,我们要获取它的退出结果,次低8位代表子进程退出时的退出码,最低的7个比特位保存退出时的退出信号,而core dump代表进程退出时是否具备core dump,core dump是核心转储标志,代表是否发生了核心转储。

一般而言,云服务器(生产环境)的核心转储功能是被关闭的

ulimit -a查看当前服务器相关资源配置

打开了当前的core file选项由0变为10240

此时程序跑起来,kill -8 ,我们发现此时多了一个core dump和一个临时文件

我们看到这个文件在所有文件中大小算是比较大的了

核心转储:当进程出现某种异常的时候,是否由OS将当前进程在内存种的相关核心数据,转存到磁盘中。保存到了如图所示的core文件。核心转储主要是为了调试。

此时我们不捕捉这俩个信号

运行程序,分别用2号和3号信号进程退出,3号信号退出时出现了core dump

此时又有了核心转储

我们可以看到里面还有Ign(忽略),cont(继续)

此时运行程序,程序直接终止

产生了core文件

GDB调试

我们先输入gdb mysignal,之后输入core -file core.26559,此时直接定位到出错的地方而且有出错的原因,我们就不需要像以前一样一行一行调试

验证进程等待中的core dump标记位

这个标记为代表是否发生核心转储

我们可以看到发生了核心转储

多了一个core文件

我们sleep(100),之后运行程序 使用kill -2

此时core dump标记位为0

我们关闭核心转储,core dump标记位为0

为什么生产环境一般都是要关闭core dump?

core文件产生过多可能会把磁盘写满,造成无法预估的后果。

调用系统接口发送信号

kill

man 2 kill

向指定的进程发送指定的信号。

使用kill写一个程序

我们此时sleep(10000),然后运行我们的程序,进程被杀掉

raise

如果kill是向指定的进程发送指定的信号,kill就是向自己发送指定的信号

自己给自己发送8号信号

abort

abort让进程直接终止, 给自己发送abort信号(自己终止自己)。

输入ulimit -c 10240打开core,此时再运行程序

abort通常用来终止进程。

用户调用系统接口->执行OS对应的系统调用代码->OS提取参数或者设置特定的数值->OS向目标进程写信号->修改对应进程的信号标记位->进程后续会处理信号->执行对应的动作

由软件条件产生信号

管道,读端不光不读,而且关闭了,写端一直在写,会发生什么?

此时意味着写没有意义,OS会自动终止对应的写端进程,通过发送信号的方式,发送SIGPIPE(13号信号)。

SIGALARM是14号信号

#include <unistd.h>
unsigned int alarm(unsigned int seconds);
调用alarm函数可以设定一个闹钟,也就是告诉内核在seconds秒之后给当前进程发SIGALRM信号, 该信号的默认处理动
作是终止当前进程。

这个函数的返回值是0或者是以前设定的闹钟时间还余下的秒数。打个比方,某人要小睡一觉,设定闹钟为30分钟之后

响,20分钟后被人吵醒了,还想多睡一会儿,于是重新设定闹钟为15分钟之后响,“以前设定的闹钟时间还余下的时间”就

是10分钟。如果seconds值为0,表示取消以前设定的闹钟,函数的返回值仍然是以前设定的闹钟时间还余下的秒数

上面这段程序验证1s之内,能运算多少次count++;

为什么只计算到6w多呢?因为我们进行了cout,而且因为我们的Xshell在本地,云服务器在远端,cout还是通过网络发送的,因此会比较慢。

若单纯想计算算力,可这样做

我们每发送14号信号count值就会被发出来

我们设定了一个闹钟,这个闹钟一旦触发,就自动移除了(设置一次就只会触发一次)

我们在每次捕捉到信号时,再设置一个闹钟

每隔一秒打印一条消息

我们上面实现了类似的定时器功能

每隔一秒打印一下

#include <iostream>
#include <string>
#include <vector>
#include <functional>
#include <unistd.h>
#include <sys/types.h>
#include <sys/wait.h>
#include <signal.h>
#include <stdlib.h>

using namespace std;

 typedef function<void ()> func;
 vector<func> callbacks;

 uint64_t count = 0;

 void showCount()
 {
     // cout << "进程捕捉到了一个信号,正在处理中: " << signum << " Pid: " << getpid() << endl;
     cout << "final count : " << count << endl;
 }
 void showLog()
 {
     cout << "这个是日志功能" << endl;
 }
 void logUser()
 {
     if(fork() == 0)
     {
         execl("/usr/bin/who", "who", nullptr);
         exit(1);
     }
     wait(nullptr);
 }
 void flushdata()
 {

 }

 // 定时器功能
 // sig: 
 void catchSig(int signum)
 {
     for(auto &f : callbacks)
     {
         f();
     }
     alarm(1);
 }
 static void Usage(string proc)
 {
     cout << "Usage:\r\n\t" << proc << " signumber processid" << endl;
 }

void handler(int signum)
{
    sleep(1);
    cout << "获得了一个信号: " << signum << endl;
     exit(1);
}
int main(int argc, char* argv[])
{
    signal(SIGFPE, handler);
    alarm(1);
    callbacks.push_back(showCount);
    callbacks.push_back(showLog);
    callbacks.push_back(logUser);
    while (true) count++;
    return 0;
}

我们可以发现IO的效率非常低,尤其是带上网络。

如何理解软件条件产生信号?

OS先识别到某种软件条件触发或者不满足,然后OS构建信号,发送给指定的进程

硬件异常产生信号

捕捉了一个信号,但为什么这里开始循环了?

如何理解除0?

  1. 进行计算的是CPU,这个硬件

  1. CPU内部是有寄存器的,其中有一个是状态寄存器(位图),里面保存每次计算的计算状态,状态寄存器有对应的标志位,有溢出标记为,OS会自动进行计算完毕之后的检测。如果溢出标记位是1,OS识别到有溢出问题,立即找到当前谁在运行提取PID,OS完成信号发送的过程,进程会在合适的时候,进行处理。

  1. 除0错误本质是硬件异常。

  1. 一旦出现硬件异常,进程不一定退出,一般默认是退出,但是即便不退出,我们也做不了什么

  1. 为什么会死循环?寄存器中的异常一直没有被解决,OS不断地重复发送信号

我们写一个段错误

段错误本质也是收到信号

此时又陷入了死循环。

如何理解野指针和越界问题?

  1. 都必须通过地址找到目标位置

  1. 语言上面的地址全部都是虚拟地址,

  1. 将虚拟地址转为物理地址

  1. 通过页表+MMU(Memory Manager Unit是硬件)找到物理内存

  1. 野指针,越界-》非法地址,MMU转换的时候一定会报错。错误会被OS转成信号发送给进程

所有的信号,都有它的来源。但最终全部是被OS识别,解释并发送的。

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

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

相关文章

【Windows线程开发】线程基础

本篇文章来带领大家了解Windows线程&#xff0c;了解线程的基本概念&#xff0c;了解线程的创建方式&#xff0c;以及一些简单的线程操作。 文章目录 一.线程基本概念二.创建线程三.线程实例&#xff08;单线程&#xff0c;多线程&#xff09;单线程执行多线程执行 四.挂起&am…

ElasticSeach 集成 springboot

声明是ElasticSearch? ElasticSearch是一个基于Lucene的搜索服务器。它提供了一个分布式多用户能力的全文搜索引擎&#xff0c; 基于RESTful web接口。Elasticsearch是用Java开发的&#xff0c;并作为Apache许可条款下的开放源码发布&#xff0c;是 当前流行的企业级搜索引擎…

大数据 | (五)通过Sqoop实现从MySQL导入数据到HDFS

知识目录 一、前言二、导入前的准备2.1 Hadoop集群搭建2.2 Hadoop启停脚本 三、docker安装MySQL四、安装Sqoop4.1 Sqoop准备4.2 Sqoop连接Mysql数据测试 五、导入MySQL数据到hdfs5.1 准备MySQL数据5.2 导入数据 六、Sqoop现状七、结语 一、前言 各位CSDN的朋友们大家好&#x…

5.11组会衍生总结:train/eval/BN、CNN与特征图、极大似然与EM、方差n与n-1(有偏估计/无偏估计)

目录组会问题:1.关于模型的train/eval与batchnorm1-1.理论1-2.实际运用(包含loss反向传播)2.CNN详解,特征图是什么CNN处理过程特征图(也叫通道)(num_features)总结(包含CNN图片的规律分析):3.极大似然估计与EM最大期望4.方差的n与n-1(有偏估计与无偏估计) 组会问题:…

企业文化和品牌文化是两回事

商业通常谈两类文化&#xff1a;企业文化&#xff0c;品牌文化 1&#xff09;组织内部的文化 2&#xff09;品牌以产品为依托&#xff0c;给消费群体营造的文化 “积极稳定”的文化氛围打造是个慢活 企业文化&#xff0c;既要挂在墙上&#xff0c;又要挂在嘴上&#xff0c;最终…

二叉查找树和平衡二叉树

二叉查找树 下面是一张数据库的表,有两列,分别是 Col1 和 Col2 我们来查找一下col289的这行数据,SQL语句如下: select * from a where col2 87没有用索引时执行上面的查询 , 数据从磁盘一条一条拿来对比最终找到结果&#xff0c;如果数据表很大,数据又在表尾的话,需要花费非…

Open3D点云数据处理(一):VSCode配置python,并安装open3d教程

文章目录 1 python下载与安装1.1 python下载1.2 python安装1.3 验证python是否安装成功 2 VSCode下载与安装2.1 下载2.2 安装2.3 安装汉化插件2.4 vscode安装python扩展2.5 编写一个简单的python程序并运行2.6 在外部终端中打印运行结果2.7 测试代码&#xff1a;使用python画一…

常用的网页设计工具,有哪些比较推荐

网页设计并不容易&#xff0c;易于使用的网页设计工具更难找到。随着网络的快速发展&#xff0c;网站迅速崛起&#xff0c;网页设计也很流行。本文收集了7款易于使用的网页设计工具&#xff0c;每一种近年来都受到网页设计师的广泛欢迎&#xff0c;以确保实用和易于使用。我希望…

背包九讲(dp问题详解)

一、01背包问题 首先了解一下题目&#xff1a; 有 N 件物品和一个容量是 V 的背包。每件物品只能使用一次。 第 i 件物品的体积是 vi&#xff0c;价值是 wi。 求解将哪些物品装入背包&#xff0c;可使这些物品的总体积不超过背包容量&#xff0c;且总价值最大。 输出最大价值。…

Java中的抽象类介绍

Java中的抽象类介绍 抽象类可以包含普通类的成员&#xff0c;它可以包含普通的属性、方法和内部类等成员。这些成员既可以被抽象类的子类继承和使用&#xff0c;也可以被抽象类自身使用。抽象类中的非抽象方法必须要有具体实现&#xff0c;否则无法通过编译。抽象类中也可以拥…

Leetcode2379. 得到 K 个黑块的最少涂色次数

Every day a Leetcode 题目来源&#xff1a;2379. 得到 K 个黑块的最少涂色次数 解法1&#xff1a;滑动窗口 首先题目给出一个下标从 0 开始长度为 n 的字符串 blocks&#xff0c;其中 blocks[i] 是 ‘W’ 或者 ‘B’ &#xff0c;分别表示白色块要么是黑色块。 现在我们可…

抗体偶联药物都有哪些?(详细名单)

抗体偶联药物ADC简介 抗体-药物偶联物或ADC是一类生物制药药物&#xff0c;设计用于治疗癌症的靶向疗法。与化学疗法不同&#xff0c;ADC 旨在靶向并杀死肿瘤细胞&#xff0c;同时保留健康细胞。截至 2023 年5月&#xff0c;约有 433 家制药公司正在开发 ADC。 ADC 是由与具有…

SPI基础

SPI硬件接口 SPI协议使用3条总线以及片选线。3条总线分别是SCK、MOSI、MISO&#xff0c;片选线为SS(NSS、CS) SPI基础属性 主从模式&#xff1a;主机模式&#xff0c;从机模式 通讯频率&#xff1a;不定&#xff0c;根据设备速率确定 数据位数&#xff1a;4位、7位&#xff…

基于狮群算法优化的核极限学习机(KELM)分类算法-附代码

基于狮群算法优化的核极限学习机(KELM)分类算法 文章目录 基于狮群算法优化的核极限学习机(KELM)分类算法1.KELM理论基础2.分类问题3.基于狮群算法优化的KELM4.测试结果5.Matlab代码 摘要&#xff1a;本文利用狮群算法对核极限学习机(KELM)进行优化&#xff0c;并用于分类 1.KE…

【华为机试】——每日刷题经验分享

【华为机试】——每日刷题经验分享&#x1f60e; 前言&#x1f64c;题目&#xff1a;HJ9 提取不重复的整数 总结撒花&#x1f49e; &#x1f60e;博客昵称&#xff1a;博客小梦 &#x1f60a;最喜欢的座右铭&#xff1a;全神贯注的上吧&#xff01;&#xff01;&#xff01; &a…

被ChatGPT“抢饭碗”的人

ChatGPT问世至今&#xff0c;互联上讨论声绵延不绝。有人说&#xff0c;AI会替代基础性工作。 一名金融从业者对《橡果商业评论》表示&#xff0c;这实际上是对人类经验的替代&#xff0c;那些引以为傲的经验&#xff0c;来源于对历史的总结&#xff0c;AI出现后&#xff0c;“…

【C++STL】红黑树(更新中)

前言 上篇博客学习了平衡二叉搜索树(AVLTree)&#xff0c;了解到AVL树的性质&#xff0c;二叉搜索树因为其独特的结构&#xff0c;查找、插入和删除在平均和最坏情况下都是O(logn)。AVL树的效率就是高在这个地方。 但是在AVL树中插入或者删除结点&#xff0c;使得高度差的绝对…

【GO 编程语言】数组

数组 文章目录 数组一、数组是什么二、初始化数组三、数组的遍历四、数组类型五、数组排序 一、数组是什么 Go 语言提供了数组类型的 数据结构。 数组是具有相同唯一类型的一组已编号且长度固定的数据项序列,这种类型可以是任意的原始类型。例如整型、字符串或者自定义类型。 …

HTTP第八讲——请求方法

目前 HTTP/1.1 规定了八种方法&#xff0c;单词都必须是大写的形式 GET&#xff1a;获取资源&#xff0c;可以理解为读取或者下载数据&#xff1b;HEAD&#xff1a;获取资源的元信息&#xff1b;POST&#xff1a;向资源提交数据&#xff0c;相当于写入或上传数据&#xff1b;P…

echarts 如何保存为图片时,如何同时保存滚动条隐藏的数据

echarts 如何保存为图片&#xff0c;如何保存滚动条隐藏的数据 效果展示上代码内容讲解面临的问题解决思路&#xff08;当前代码的思路&#xff09; 效果展示 这是直接将保存的图片显示在网页下方了 上代码 <!DOCTYPE html> <html><head><meta charse…