LInux-信号1

文章目录

  • 前言
  • 一、信号是什么?
  • 二、学习步骤
    • 使用kill -l命令查看信号列表
        • 可以看到有那么多信号,那么进程是如何识别这么多信号的呢?
    • 使用kill命令终止进程
    • 信号的捕捉
        • kill函数
        • raise函数
        • abort函数
    • Core dump
        • 如何查看自己的核心转储功能是否被打开?
        • 如何打开核心转储功能?
    • 由软件条件产生信号
    • 由硬件异常产生信号


前言

本章主要讲信号的产生与处理以及信号的作用,再延展出core dump的相关概念,信号对于进程十分重要。


一、信号是什么?

信号在我们的日常生活中也应用广泛,如信号灯,当绿灯亮起,我们就知道这条马路我们可以通行。我们今天所学习的信号也是同样的作用,是要让进程接受到不同信号所进行不同的处理方式。

二、学习步骤

使用kill -l命令查看信号列表

在之前学习进程状态的时候,我们就曾使用过kill命令来终止进程,而kill命令就是专门用来给进程发送信号的,那么常见的信号有哪些?
可以通过在shell输入

kill -l

信号列表

可以看到有那么多信号,那么进程是如何识别这么多信号的呢?

在每一个进程的PCB中都存储相对应的信号位图结构,那么我们就可以大概知道,这种位图结构只需要由0置1就可以实现对信号的接受,而实际上也就是如此。

我们再来看上面这幅图,左边是它们的信号编号,右边则是它们的宏名称。
在这里插入图片描述

我们今天所讨论的是1-31的信号,其中34以上的信号为实时信号,不在我们本章的学习范畴中。

使用kill命令终止进程

我们可以先写一个死循环程序,使用kill终止进程
在这里插入图片描述
在这里插入图片描述
右侧在跑死循环程序,左侧使用ps axj命令查看运行进程的pid,再使用kill -2 pid命令来终止该进程。

所以这里我们就是对目标进程使用2号信号来终止该进程。

信号的捕捉

进程对于信号有三种处理方式:
1.默认处理
2.忽略(忽略也是一种处理方式,一般是等到合适的时间再进行信号处理)
3.自定义(捕捉信号)

对于信号的捕捉,系统给了我们这样一个接口函数,使用man 2 signal查看signal函数
在这里插入图片描述
这里的sighandler_t是函数指针。

signal函数的主要作用就是用于自定义捕捉信号,将signum的信号处理方式变换成handler的处理方式

代码如下(示例):

#include<iostream>
#include<cstdlib>
#include<unistd.h>
#include<signal.h>

void catchSign(int signum)
{
    std::cout << "捕捉到" << signum << "号信号 pid:" << getpid() << std::endl;
}
int main()
{
    signal(SIGINT,catchSign);
    //signal(2,catchSign);
    while(true)
    {
        std::cout << "hello " << getpid() << std::endl; 
        sleep(1);
    }
    return 0;
}

运行这一串代码之后,我们再尝试使用kill -2 pid 命令,就会发现
在这里插入图片描述
进程收到2号信号后不是终止进程,而是打印出我们catchSign的内容
然后如果你这个时候先想用ctrl+C来终止进程,你会发现也无法终止进程
在这里插入图片描述
这是为什么? 因为ctrl+C这一组合键就是被OS识别为向前台进程发送2号信号!
我们还可以使用ctrl+\来终止进程。而ctrl+\其实也是被OS识别为向前台进程发送3号信号。

kill函数

在这里插入图片描述
shell命令有kill命令,C语言也提供了一个kill函数,可以向pid进程发送sig号命令。

raise函数

在这里插入图片描述
这个函数也是C语言提供的函数,用于对自己这个进程发送sig信号。

abort函数

在这里插入图片描述abort函数使当前进程接收到(6)SIGABRT信号而异常终止。

Core dump

通过在shell输入 man 7 signal我们可以看到
在这里插入图片描述
Term代表终止,那么Core呢? 我们刚刚也尝试使用了3号信号,进程仍然也终止了。这里的Core其实是指 触发该信号可能会发生Core dump(核心转储).

曾经我们在学习进程退出的时候,我们对于进程的退出状态有过探讨,如果进程由于收到信号异常退出,第8个bit位为core dump标志。 所以,核心转储到底是什么? 它其实是为了保护进程在运行过程中所产生的数据,将内存的数据转储到磁盘中, 这就是核心转储!

示例代码:

#include<iostream>
#include<cstdlib>
#include<unistd.h>
#include<signal.h>
#include<wait.h>
int main()
{
    pid_t id = fork();
    if(id == 0)
    {
        sleep(1);
        std::cout<<"子进程 " << getpid() << ":即将异常退出" << std::endl;
        raise(SIGQUIT);
    }
    int status = 0;
    waitpid(id, &status, 0);
    std::cout << "父进程: " << getpid() << " 子进程: " << id << " exit sign: " <<\
    (status & 0x7F) << " is core: " << ((status >> 7) & 1 ) << std::endl;
    return 0;
}

这段代码主要是让子进程向自己发送3号信号,并且3号信号是Core,父进程用status接收子进程的退出状态,通过按位与和右移bit位的方式,我们分别可以得到子进程退出时收到的信号和Core dump位。

运行如下
在这里插入图片描述

奇怪了,为什么这里的core还是0呢? 实际上是因为我这里使用的是远端云服务器,而在云服务器上,核心转储功能是被默认关闭的!如果你使用的是虚拟机,虚拟机是默认打开的!

如何查看自己的核心转储功能是否被打开?

在shell输入ulimit -a命令
在这里插入图片描述

如何打开核心转储功能?

在shell输入ulimit -c size

需要注意的是core file的单位是block,因为要存储进程中所产生的数据还是要一定的磁盘空间来存储的,所以size不能太小。
在这里插入图片描述
注意:如果这里修改core file size 失败,尝试使用sudo来添加root权限。

这次我们打开了核心转储功能,再来试试上面的代码运行结果是否不同。
在这里插入图片描述
这次我们的core dump位成功为1,并且我们当前路径下还多出了一个core文件,该文件为二进制文件。

由软件条件产生信号

顾名思义,就是达到软件某种条件则会产生的信号,我们以alarm和SIGALRM信号为例。

先来看看alarm函数
在这里插入图片描述
调用alarm函数可以设定一个闹钟,也就是告诉内核在seconds秒之后给当前进程发SIGALRM信号, 该信号的默认处理动作是终止当前进程。

像alarm给进程设一个闹钟,当闹钟时间到了,达到了设定条件就发送信号,就叫做由软件条件产生信号。

通过alarm我们可以来测一测我们cpu每秒运算能力。

#include<iostream>
#include<cstdlib>
#include<unistd.h>
#include<signal.h>
#include<wait.h>

long long count = 0;

void catchALRM(int signum)
{
    std::cout << "count: " << count << std::endl;
    alarm(1);
}

int main()
{
    signal(SIGALRM,catchALRM);
    alarm(1);

    while(1)
    {
        ++count;
    }
    return 0;
}

在这里插入图片描述
这就是我的云服务器的cpu运算能力。

由硬件异常产生信号

对于我们而言最常见的就是除0的浮点数异常和野指针所产生的越界访问的异常。
这种其实是硬件上所发现的异常,然后再对进程发送终止信号。

先说SIGFPE浮点数异常信号,大家应该都知道我们程序内部进行的运算都是由cpu进行的,当出现除0时,cpu的状态寄存器会记录浮点数错误,然后OS在计算完毕后进行检查就会发送对进程发送SIGFPE信号。

野指针也是一样的,我们的进程中的虚拟内存的数据要映射到物理内存,会经过MMU(Memory Manager Unit内存管理单元)发现越界访问,也就发送对应的SIGSEGV信号,Segmentation violation段错误。


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

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

相关文章

C++运算符重载、迭代器、继承、派生类的构造与析构、重载、隐藏和覆盖

运算符重载 普通的C运算符重载成员方法基本都知道&#xff0c;如果没有定义成员方法&#xff0c;那么编译器会优先寻找全局重载运算符看看是否匹配。这里给出了一个使用友元函数和全局重载运算符来实现整数与复数类对象的相加运算。 #include <iostream>class Complex …

Flink双流(join)

一、介绍 Join大体分类只有两种&#xff1a;Window Join和Interval Join Window Join有可以根据Window的类型细分出3种&#xff1a;Tumbling(滚动) Window Join、Sliding(滑动) Window Join、Session(会话) Widnow Join。 &#x1f338;Window 类型的join都是利用window的机制…

蜂鸣器实验

1.有源蜂鸣器简介 蜂鸣器常用于计算机、打印机、报警器、电子玩具等电子产品中&#xff0c;常用的蜂鸣器有两种&#xff1a; 有源蜂鸣器和无源蜂鸣器&#xff0c;这里的有“源”不是电源&#xff0c;而是震荡源&#xff0c;有源蜂鸣器内部带有震荡 源&#xff0c;所以有源蜂…

OD(8)之Mermaid流程图(flowcharts)使用详解

OD(8)之Mermaid流程图(flowcharts)使用详解 Author: Once Day Date: 2024年2月20日 漫漫长路才刚刚开始… 全系列文章可参考专栏: Linux实践记录_Once_day的博客-CSDN博客 参考文章: 关于 Mermaid | Mermaid 中文网 (nodejs.cn)Mermaid | Diagramming and charting tool‍…

Maven 私服 Nexus3

一、Maven和Nexus3 简介 Maven是一个采用纯Java编写的开源项目管理工具&#xff0c;采用一种被称之为Project Object Model(POM)概念来管理项目&#xff0c;所有的项目配置信息都被定义在一个叫做POM.xml的文件中, 通过该文件Maven可以管理项目的整个生命周期&#xff0c;包括…

maven 打包命令

Maven是基于项目对象模型(POM project object model)&#xff0c;可以通过一小段描述信息&#xff08;配置&#xff09;来管理项目的构建&#xff0c;报告和文档的软件项目管理工具。 Maven的核心功能便是合理叙述项目间的依赖关系&#xff0c;通俗点讲&#xff0c;就是通过po…

06 分频器设计

分频器简介 实现分频一般有两种方法&#xff0c;一种方法是直接使用 PLL 进行分频&#xff0c;比如在 FPGA 或者 ASIC 设计中&#xff0c;都可以直接使用 PLL 进行分频。但是这种分频有时候受限于 PLL 本身的特性&#xff0c;无法得到频率很低的时钟信号&#xff0c;比如输入 …

Predis Multi-Zone

A Data Flow Framework with High Throughput and Low Latency for Permissioned Blockchains 联盟链的吞吐瓶颈由共识层和网络层的数据分发过程共同决定。 Predis 协议利用了共识节点的空闲带宽&#xff0c;提前分发区块中的内容即bundle&#xff0c;减少了共识区块中的内容&…

2024龙年特别篇 -- 魔法指针 之 assert断言 传址调用 传值调用

你是否为 assert断言&#xff0c;传址调用&#xff0c;传值调用而进一步加深印象&#xff0c;接下来就让白子寰同学为你详细讲解&#xff01;&#xff01;&#xff01; 目录 assert断言 概念 assert介绍 #define NDEBUG的使用 注意事项 传值调用 VS 传址调用 传值调用…

C语言推荐书籍

本书详细讲解了C语言的基本概念和编程技巧。全书共17章。第1章、第2章介绍了C语言编程的预备知识。第3章&#xff5e;第15章详细讲解了C语言的相关知识&#xff0c;包括数据类型、格式化输入/输出、运算符、表达式、语句、循环、字符输入和输出、函数、数组和指针、字符和字符串…

CS_Smb_Beacon上线不出网机器

当我们想上线不出网的机器的时候&#xff0c;我们可以通过上传工具来实现&#xff0c;但是有没有不用上传工具的方法呢&#xff1f;&#xff1f;&#xff1f; 有&#xff01;&#xff01;&#xff01; 而且cs会自带&#xff01;&#xff01;&#xff01; 1.基础的网络拓扑 以下…

MYSQL数据库详解

一、数据库的基本概念 数据&#xff08;data&#xff09;&#xff1a;指对客观事物进行描述并可以鉴别的符号。这些符号是可识别的&#xff0c;抽象的。 比如数字、图片、音频等。 数据库管理系统&#xff08;DBMS&#xff09;&#xff1a;数据库极其管理它的软件组成。 数据库…

RocketMQ-架构与设计

RocketMQ架构与设计 一、简介二、框架概述1.设计特点 三、架构图1.Producer2.Consumer3.NameServer4.BrokerServer 四、基本特性1.消息顺序性1.1 全局顺序1.2 分区顺序 2.消息回溯3.消息重投4.消息重试5.延迟队列&#xff08;定时消息&#xff09;6.重试队列7.死信队列8.消息语…

2.21C语言学习

Floyd算法原理 Floyd算法是一个经典的动态规划算法&#xff0c;它又被称为插点法。该算法名称以创始人之一、1978年图灵奖获得者、斯坦福大学计算机科学系教授罗伯特弗洛伊德命名。Floyd算法是一种利用动态规划的思想寻找给定的加权图中多源点之间最短路径的算法,算法目标是寻找…

工厂方法模式Factory Method

1.模式定义 定义一个用于创建对象的接口&#xff0c;让子类决定实例化哪一个类。Factory Method 使得一个类的实例化延迟到子类 2.使用场景 1.当你不知道改使用对象的确切类型的时候 2.当你希望为库或框架提供扩展其内部组件的方法时 主要优点&#xff1a; 1.将具体产品和创建…

解决NPE的三种方式

解决NPE的三种方式 NullPointerException&#xff08;空指针异常&#xff0c;NPE&#xff09;是Java编程中常见的错误。解决NPE的方法可以从以下三个方面考虑&#xff1a; 明确处理空引用情况&#xff1a; 在某些情况下&#xff0c;无法避免使用可能为空的引用对象。此时&…

【漏洞复现】H3C SecParh堡垒机任意用户登录漏洞

Nx01 产品简介 H3C SecParh堡垒机是一款专业用于安全管理的堡垒机产品&#xff0c;它通过强大的访问控制功能和安全审计功能&#xff0c;实现对网络服务器的远程安全管理和监控。 Nx02 漏洞描述 H3C SecParh堡垒机的get_detail_view.php中存在任意用户登录漏洞。攻击者可以构建…

计算机体系架构初步入门

&#x1f3ac;个人简介&#xff1a;一个全栈工程师的升级之路&#xff01; &#x1f4cb;个人专栏&#xff1a;高性能&#xff08;HPC&#xff09;开发基础教程 &#x1f380;CSDN主页 发狂的小花 &#x1f304;人生秘诀&#xff1a;学习的本质就是极致重复! 目录 1 计算机五大…

备战蓝桥杯---动态规划(应用2(一些十分巧妙的优化dp的手段))

好久不见&#xff0c;甚是想念&#xff0c;最近一直在看过河这道题&#xff08;感觉最近脑子有点宕机QAQ&#xff09;&#xff0c;现在算是有点懂了&#xff0c;打算记录下这道又爱又恨的题。&#xff08;如有错误欢迎大佬帮忙指出&#xff09; 话不多说&#xff0c;直接看题&…

2024三掌柜赠书活动第十一期:精通区块链开发技术(第2版)

目录 前言关于区块链开发技术关于《精通区块链开发技术(第2版)》编辑推荐内容简介作者简介图书目录书中前言/序言《精通区块链开发技术(第2版)》全书速览结束语 前言 作为开发者经常在技术圈活动&#xff0c;会接触各种前沿技术&#xff0c;比如区块链技术的崛起引发了全球范…