Linux信号机制探析--信号的产生

🍑个人主页:Jupiter.
🚀 所属专栏:Linux从入门到进阶
欢迎大家点赞收藏评论😊

在这里插入图片描述

在这里插入图片描述

目录

  • `📚信号`
            • `什么是信号?`
            • `为什么要有信号?`
            • 查看Linux系统中信号
    • `🎈信号产生`
      • `📕kill 命令产生信号`
      • `🏠键盘产生 `
      • `🦅系统调用`
            • kill系统调用
            • raise系统调用
            • abort系统调用
      • `🍑软件条件`
      • `🌠硬件异常产生信号`
        • 对于键盘产生信号的理解
        • 对硬件异常产生信号的理解
            • 为什么默认的是core dump(核心转储)功能是关闭的呢


📚信号

什么是信号?
  • 信号是Linux系统提供的让进程或则操作系统给其他进程发送异步信息的一种方式。

  • 信号的产生是随时产生的,进程无法预料,所以信号是异步发送的。(信号的产生是由别的进程产生的,在收到信号之前,我(进程)在做自己的事情,我和发送信号的进程是在并发跑的。所以是异步)

为什么要有信号?
  • Linux系统中要有信号,主要是为了提供一种机制,以便异步地处理系统事件和进程间通信。

    • 进程间通信:信号是进程间通信(IPC)的一种方式,允许进程之间异步地传递消息。
    • 系统事件通知:操作系统可以使用信号来通知进程发生了系统级事件,如非法内存访问(段错误)、软件终止请求(如用户按下Ctrl+C)等。
    • 简化编程模型:信号提供了一种机制,允许操作系统和应用程序开发者以一种标准化的方式处理各种异步事件,从而简化了编程模型。
    • 资源管理:信号可以用于管理进程占用的资源。例如,当进程占用的资源超出限制时,系统可以发送信号来终止或暂停该进程。
    • 用户交互:用户可以通过发送信号来控制进程的行为,例如,使用kill命令发送信号以终止或暂停进程。
    • 错误处理:当进程执行非法操作时,系统可以发送信号来通知进程发生了错误,进程可以根据信号的指示进行错误处理。
查看Linux系统中信号
  • kill -l命令可以查看系统定义的信号列表:
  • 每个信号都有一个编号和一个宏定义名称,这些宏定义可以在signal.h中找到,例如其中有定义 #define SIGINT 2
  • 编号34以上的是实时信号,本章只讨论编号34以下的信号,不讨论实时信号。这些信号各自在什么条件下产生,默认的处理动作是什么,在signal(7)中都有详细说明: man 7 signal
  • 注意:没有0 ,32 ,33号信号

🎈信号产生

📕kill 命令产生信号

  • 如:杀掉指定进程: kill -9 进程编号

🏠键盘产生

  • 如:2号信号 :ctrl + c 可以终止进程 3号信号:ctrl + \ 终止进程
  • 会将该组合键解释为信号 --> 向目标进程发送该信号 —> 进程收到信号 —> 响应信号。

🦅系统调用

kill系统调用

函数介绍:

  • 功能: 向任意的进程发送任意的信号。

  • 参数:参数一:进程pid ; 参数二:信号编号或则信号名称。

  • 返回值: 0表示成功,-1表示失败。

示例代码:

void handler(int signo)
{cout << "receive a signal: " << signo << endl;
}
int main()
{signal(2,handler);int n = kill(getpid(),2);  //给自己发送2号信号return 0;
}

运行结果预期:使用kill系统调用给自己发送一个2号信号,2号信号被捕捉,当收到二号信号的时候,执行我们写的handler函数,打印信息 :receive a signal:2

运行结果:
在这里插入图片描述

raise系统调用

函数介绍:

  • 功能:谁调用,就向哪一个进程发送任意信号

  • 参数:信号编号/信号名称

  • 返回值:0表示成功,非0表示失败。

代码示例:

void handler(int signo)
{cout << "receive a signal: " << signo << endl;
}int main()
{signal(2,handler);int n  = raise(2);return 0;
}

运行结果:
在这里插入图片描述

abort系统调用

函数介绍:

  • 功能:向调用该函数的进程发送6号信号:SIGABRT(终止进程)。

示例代码:

int main()
{int cnt = 1;while(cnt++){if(cnt == 5){abort();}cout<<"i am a process,pid:"<<getpid()<<endl;}return 0;
}

运行结果:
在这里插入图片描述

🍑软件条件

SIGPIPE是一种由软件条件产生的信号(管道的读端不读,还关闭了读文件描述符,则写端就会因为写条件不具备而被OS终止,OS给写端进程发送的信号就是SIGPIPE:13号信号)。本节还介绍alarm函数SIGALRM信号

函数介绍:

  • 调用alarm函数可以设定一个闹钟,也就是告诉内核在seconds秒之后给当前进程发SIGALRM信号, 该信号的默认处理动作是终止当前进程。

这个函数的返回值是0或者是以前设定的闹钟时间还余下的秒数。比如:当我们设定一个50秒的闹钟,如果在20秒的时候,提前给该进程发送一个SIGALRM信号使进程提前响应,这时,返回值就为50-20=30。

alarm(0):取消闹钟

示例代码:

int main()
{alarm(5);while(true){cout<<"i am a process,pid:"<<getpid()<<endl;sleep(1);}return 0;
}

运行结果:
在这里插入图片描述

对SIGALRM信号进行捕捉,实现2秒循环的闹钟
代码实现:

void handler(int signo){cout << "receive a signal: " << signo << endl;alarm(2);
}
int main()
{signal(SIGALRM,handler);alarm(2);while(true){cout<<"i am a process,pid:"<<getpid()<<endl;sleep(1);}return 0;
}

运行结果:
在这里插入图片描述

🌠硬件异常产生信号

硬件异常被硬件以某种方式被硬件检测到并通知内核,然后内核向当前进程发送适当的信号。

  • 例如当前进程执行了除以0的指令,CPU的运算单元会产生异常,内核将这个异常解释 为SIGFPE信号发送给进程。
  • 再比如当前进程访问了非法内存地址,MMU会产生异常,内核将这个异常解释为SIGSEGV信号发送给进程。

除0异常示例代码:

int main()
{int a = 0;int b = 4/0;while(true){}sleep(1);return 0;
}

运行结果:
在这里插入图片描述

访问空指针示例代码:

int main()
{int *p = 0;*p=10;return 0;
}

运行结果:
在这里插入图片描述

对于键盘产生信号的理解

字符输入(字符设备),组合键输入(输入的命令),对于键盘来说,输入的一律当成字符处理,至于到底是字符还是命令,是需要OS键盘驱动来联合解释的。

OS怎么知道键盘在输入数据?(简略介绍)

  • 使用了一种硬件中断的技术。
  • 在开机的时候,OS已经形成了一张中断向量表(函数指针数组),这张表可以提前注册很多对软硬件操作的方法,比如下面表中2号位置是从键盘中读取数据,CPU底部由很多的针脚与外设相连接,这些针脚都有自己的编号当OS正在执行常规代码得时候,用户按键盘输入数据得时候,会给CPU上的特定针脚触发特定的硬件中端,CPU就会将该针脚编号放到一个寄存器中,这时候硬件到软件的动作就完成了,然后CPU就会要求OS停止当前正在执行的工作,让OS根据中端号,取中端向量表中查找对应的操作方法,然后去执行读取键盘数据的任务。
    在这里插入图片描述

通过上面的操作后,已经读取到了数据了,接下来会对读取的数据进行判定

如果操作系统判定为是一般字符输入,则直接放到键盘缓冲区中,如果判定为控制命令OS则会将控制命令解释成信号,然后将信号发送给进程

对硬件异常产生信号的理解
  • 除0错误问题

    首先,计算均在CPU中进行的,对于除0错误的计算过程中,会将标志寄存器中的溢出位的0置为1,将计算错误表现到CPU的寄存器上(硬件上),然后CPU发现硬件出现异常,这时OS会介入,发现问题后,将对应的信号发送给相应的进程。

  • 野指针问题

    CPU有一个硬件MMU,专门负责虚拟地址到物理地址的转换,同时又两个寄存器,CR2与CR3,如果虚拟地址转换成功,会将转换好的物理地址放到CR3中,如果转换出错,则会将错误标志信息放到CR2中,当野指针的时候,首先将野指针地址放到一个寄存器中,然后通过MMU进行转换,在转换的过程中,发现页表中没有这个虚拟地址或则该虚拟地址中没有相应的权限,则会转换出错,将错误标记放在CR2中,表明了CR2出异常,硬件出现异常,这时OS会介入,发现问题后,将对应的信号发送给相应的进程。
    在这里插入图片描述
    一个进程,出现异常大多都是将进程终止,但是man 7 signal 中,终止又两种,一个Term,一个是Core,他们有什么区别呢?以及之前在讲进程的时候,进程等待的status位图core dump标记位和这个Core的关系。
    在这里插入图片描述
    在这里插入图片描述

Core Dump

首先解释什么是Core Dump。当一个进程要异常终止时,可以选择把进程的用户空间内存数据全部保存到磁盘上,文件名通常是core,这叫做Core Dump。进程异常终止通常是因为有Bug,比如非法内存访问导致段错误,事后可以用调试器检查core文件以查清错误原因,这叫做Post-mortem Debug(事后调试)。一个进程允许产生多大的core文件取决于进程的Resource Limit(这个信息保存 在PCB中)。默认不允许产生core文件的,因为core文件中可能包含用户密码等敏感信息,不安全。

  • 查看core是否打开 指令:ulimit -a
    在这里插入图片描述

  • 开启Linuxcore dump功能:用ulimit命令改变这个限制,允许产生core文件。 首先用ulimit命令改变Shell进程的Resource Limit,允许core文件最大为1024K: $ ulimit -c 1024
    在这里插入图片描述
    打开过后,再运行一个除0错误的程序,会再当前工作目录中形成一个core文件(ubuntu系统),文件的名字在不同的平台不同(centos系统中就是以core.进程编号命名的)。

事后调试

gdb 可执行程序 —>core-file core 就会将相关调试信息列出(比如,在哪一行出错,出什么错)。

为什么默认的是core dump(核心转储)功能是关闭的呢
  • 有一些平台的core命名不同,如果每一个进程出现core dump后,都形成不同的core文件,那么很容将服务器的磁盘打满。

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

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

相关文章

【流媒体】RTMPDump—RTMP_ConnectStream(创建流连接)

目录 1. RTMP_ConnectStream函数1.1 读取packet&#xff08;RTMP_ReadPacket&#xff09;1.2 解析packet&#xff08;RTMP_ClientPacket&#xff09;1.2.1 设置Chunk Size&#xff08;HandleChangeChunkSize&#xff09;1.2.2 用户控制信息&#xff08;HandleCtrl&#xff09;1…

JAVA面试汇总

JAVA面试 JAVA面试精华 面试精华 互联网面试真题

keepalived详解

概念 keepalived 是一款基于 VRRP&#xff08;Virtual Router Redundancy Protocol&#xff0c;虚拟路由冗余协议&#xff09;协议来实现高可用&#xff08;High Availability, HA&#xff09;的轻量级软件。它主要用于防止单点故障&#xff0c;特别是在 Linux 环境下&#xff…

使用maven快速生成打包文件

最近在部署基于SpringBoot开发的项目时&#xff0c;由于微服务较多&#xff0c;本地工程编译后只得出一个JAR包&#xff0c;部署起来实在不方便&#xff0c;因此总想着怎么偷偷懒&#xff0c;执行一次命令编译出整个部署的文件。先说结果&#xff0c;最后期望打包的目录如下&am…

C++ | 继承

前言 本篇博客讲解c中的继承 &#x1f493; 个人主页&#xff1a;普通young man-CSDN博客 ⏩ 文章专栏&#xff1a;C_普通young man的博客-CSDN博客 ⏩ 本人giee: 普通小青年 (pu-tong-young-man) - Gitee.com 若有问题 评论区见&#x1f4dd; &#x1f389;欢迎大家点赞&…

Kubernetes 如何给pod的 /etc/hosts文件里面添加条目

创建pod的时候&#xff0c;pod会在其/etc/hosts里面添加一个条目。 [rootmaster ~]# kubectl get pod -o wide NAME READY STATUS RESTARTS AGE IP NODE NOMINATED NODE READINESS GATES dns-test 1/1 R…

LLM概念梳理(二):检索增强RAG

非常感谢RAG&#xff08;检索增强生成&#xff09;技术详解&#xff1a;基于垂直领域专有数据的 Chatbots 是如何实现的&#xff0c;这篇文章对 RAG 技术进行了详细的描述。我根据自己的理解&#xff0c;并且按照代码思路重新进行整理。 RAG 技术看似神奇&#xff0c;其本质是…

图片怎么压缩得小一点?这八种免费图片压缩方法赶紧试试

在数字化时代&#xff0c;无论是工作还是日常生活中&#xff0c;图片的使用已变得不可或缺。然而&#xff0c;随着高分辨率图片的广泛应用&#xff0c;文件体积也随之增加&#xff0c;这不仅占用了大量存储空间&#xff0c;还可能导致传输和加载速度变慢。因此&#xff0c;如何…

干货:2024必备的四大PDF编辑器推荐!

面对PDF文件的编辑需求&#xff0c;你是否感到无从下手&#xff1f;那么&#xff0c;今天就为大家推荐几款实用的PDF编辑工具&#xff0c;让你轻松应对各种PDF编辑难题。 福昕PDF编辑器 链接&#xff1a;editor.foxitsoftware.cn 福昕PDF编辑器多功能专业级是我PDF编辑器。它…

python-docx 实现 Word 办公自动化

前言&#xff1a;当我们需要批量生成一些合同文件或者简历等。如果手工处理对于我们来说不仅工作量巨大&#xff0c;而且难免会出现一些问题。这个时候运用python处理word实现自动生成文件可极大的提高工作效率。 python-docx是python的第三方插件&#xff0c;用来处理word文件…

HTML 列表和容器元素——WEB开发系列10

HTML 提供了多种方式来组织和展示内容&#xff0c;其中包括无序列表、有序列表、分区元素 ​​<div>​​ 和内联元素 ​​<span>​​、以及如何使用 ​​<div>​​​ 进行布局和表格布局。 一、HTML 列表 1. 无序列表 (​​<ul>​​) 无序列表用于展…

JavaScript_11_练习:小米搜索框案例(焦点事件)

效果图 代码 <!DOCTYPE html> <html lang"en"><head><meta charset"UTF-8"><meta name"viewport" content"widthdevice-width, initial-scale1.0"><title>练习&#xff1a;小米搜索框案例&#…

C语言基础(八)

1、标准库函数&#xff1a; 测试代码1&#xff1a; #include <stdio.h> // 标准库函数头文件导入 // 自定义函数 int add(int a, int b) { return a b; } // 声明回调函数类型 typedef void (*Callback)(int); // 调用回调函数的函数 void process(Callb…

MySQL中的EXPLAIN的详解

一、介绍 官网介绍&#xff1a; https://dev.mysql.com/doc/refman/5.7/en/explain-output.htmlhttps://dev.mysql.com/doc/refman/8.0/en/explain-output.htmlexplain&#xff08;执行计划&#xff09;&#xff0c;使用explain关键字可以模拟优化器执行sql查询语句&#xff…

QT 与 C++实现基于[ TCP ]的聊天室界面

TCP客户端 Widget.h #ifndef WIDGET_H #define WIDGET_H#include <QWidget> #include <QTcpSocket> //客户端类 #include <QMessageBox> #include <QListWidgetItem> #include <QDebug>QT_BEGIN_NAMESPACE namespace Ui { class Widget; } …

SpingBoot集成kafka发送读取消息

SpingBoot集成kafka开发 kafka的几个常见概念 1、springboot和kafka对应版本&#xff08;重要&#xff09;2、创建springboot项目&#xff0c;引入kafka依赖2.1、生产者EventProducer2.2、消费者EventConsumer2.3、启动生产者的方法SpringBoot01KafkaBaseApplication2.4、appli…

map与set容器初识:初步运用map与set

前言&#xff1a; 本文主要讲解的时对于map与set容器的初步使用&#xff0c;希望大家对map与set容器不熟悉的看了之后可以快速运用set与map到日常中来。&#xff08;本文适合对vector等基础容器有一定基础的同学&#xff09; 一、set与map容器常见接口 迭代器接口与以往的所…

12 程序控制语句:循环控制(while、do-while、for、多重嵌套循环、死循环)

目录 1 while 循环 1.1 基本语法 1.2 流程图 1.3 计数循环 1.3.1 实现原则 1.3.2 案例&#xff1a;循环输出语句 1.3.3 案例&#xff1a;循环输出数字 7~15 1.3.4 案例&#xff1a;倒序输出数字 56 ~ 43 1.3.5 案例&#xff1a;输出 10&#xff08;包括 10&…

使用 Go 语言将 Base64 编码转换为 PDF 文件

使用Go语言将PDF文件转换为Base64编码-CSDN博客文章浏览阅读104次&#xff0c;点赞2次&#xff0c;收藏5次。本文介绍了如何使用 Go 语言将 PDF 文件转换为 Base64 编码&#xff0c;并保存到文件中。https://blog.csdn.net/qq_45519030/article/details/141224319 在现代编程中…

【WebSocket】websocket学习【二】

1.需求&#xff1a;通过websocket实现在线聊天室 2.流程分析 3.消息格式 客户端 --> 服务端 {"toName":"张三","message":"你好"}服务端 --> 客户端 系统消息格式&#xff1a;{"system":true,"fromName"…