【Linux探索学习】第二十七弹——信号(一):Linux 信号基础详解

Linux学习笔记:

https://blog.csdn.net/2301_80220607/category_12805278.html?spm=1001.2014.3001.5482

前言:

前面我们已经将进程通信部分讲完了,现在我们来讲一个进程部分也非常重要的知识点——信号,信号也是进程间通信的一种,本篇主要讲解信号的概念和信号的几种产生方法及对应的场景

目录

一、引言

二、信号的概念

2.1 什么是信号

2.2 信号的作用

2.3 信号的特点

2.4 常见信号列表

​编辑

三、信号的产生

3.1 前台进程和后台进程

3.2 用户产生信号

3.3 系统产生信号

3.4 软件产生信号

四、信号的处理

4.1 默认处理方式

4.2 自定义信号处理函数

五、总结


一、引言

在 Linux 操作系统中,信号(Signal)是一种进程间通信(IPC,Inter - Process Communication)的机制,它用于通知进程发生了某种异步事件。信号可以来自内核,也可以来自其他进程。进程接收到信号后,会根据信号的类型以及自身的处理方式做出相应的反应。理解信号对于编写健壮的 Linux 程序以及深入理解 Linux 操作系统的运行机制至关重要。

二、信号的概念

2.1 什么是信号

信号是一种软中断,它是一种异步通知机制。当某个特定事件发生时,如用户按下特定组合键、系统资源耗尽、进程异常终止等,系统会向相关进程发送一个信号。每个信号都有一个对应的编号和名称,例如信号 1 表示 SIGHUP(挂起信号),信号 9 表示 SIGKILL(强制终止信号)。

2.2 信号的作用

信号的主要作用是让进程能够对异步事件做出响应。例如,当用户在终端中按下 Ctrl + C 组合键时,系统会向当前前台进程发送 SIGINT 信号,通常进程会接收到这个信号后停止当前正在执行的任务并退出。信号还可以用于进程间的通信,一个进程可以向另一个进程发送信号来通知其执行某些操作。

结合2.1和2.2我们来讲解一个概念:信号是一种软中断,是什么意思呢?当我们往键盘中输入内容时是如何告诉给内核的?ctrl+c又是如何被解释为指令的呢?

我们先来看下面这张图:

        键盘实际上是通过中断来让操作系统知道自己要写入内容的,键盘被按下时,就会触发硬件中断,不同的硬件对应着不同的中断号,中断单元就可以通过它们的中断号将它们与CPU中不同的键位相连,从而使CPU中这个方向的寄存器(32位)特定位置产生电信号,操作系统中有一个叫中断向量表的类似于函数指针结构体的结构,里面保存着访问各种外设的方法,操作系统通过CPU产生的电信号就辨别出要获取哪种硬件的信息,从而通过中断向量表中的方法,将硬件中的信息拷贝到操作系统的文件缓冲区中(操作系统下一切皆文件,且每一个文件都有自己的文件缓冲中区),然后再拷贝到用户缓冲区
       同时比如键盘等外键,操作系统在获取键盘上的信息时会先进行识别,会对数据进行判断,如果是控制进程的比如ctrl+c等组合键就不会往缓冲区中拷贝,我们可以发现我们学习的信号与上面的中断过程很像,其实信号,就是用软件方式,模拟的对讲程的硬件中断,所以信号也被叫做软中断

2.3 信号的特点

  1. 异步性:信号的产生是异步的,与进程的执行顺序无关。进程在运行过程中可能随时收到信号。
  1. 简单性:信号机制相对简单,只需要一个信号编号就可以标识不同的信号。
  1. 有限性:Linux 系统中定义的信号数量是有限的,不同的系统可能略有差异,但通常在几十种左右。

2.4 常见信号列表

信号编号

信号名称

含义

默认处理方式

1

SIGHUP

挂起信号,通常在终端关闭时发送给相关进程

终止进程

2

SIGINT

中断信号,由用户按下 Ctrl + C 组合键产生

终止进程

3

SIGQUIT

退出信号,由用户按下 Ctrl + \ 组合键产生

终止进程并生成核心转储文件

9

SIGKILL

强制终止信号,不能被捕获、阻塞或忽略

立即终止进程

15

SIGTERM

终止信号,通常用于正常终止进程

终止进程

18

SIGCONT

继续信号,用于恢复被暂停的进程

继续执行进程

19

SIGSTOP

停止信号,用于暂停进程,不能被捕获、阻塞或忽略

暂停进程

可以通过kill -l指令查看所有信号

kill -l

三、信号的产生

3.1 前台进程和后台进程

先来科普一个小知识点:前台进程和后台进程,来看下面一个程序

#include<iostream>
#include<unistd.h>
using namespace std;
int main()
{while(true){cout<<"I am a crazy process"<<endl;sleep(1);}return 0;
}

我们进行编译后会得到一个可执行程序

./myfile

我们这样执行时我们会发现在程序运行的时候,我们输入其它指令比如Is,pwd等都不会有结果,进程还在继续运行,除非用ctrl+c终止掉进程,这样的进程称为前台进程

./myfile &

这种的后面加上地址符的叫做后台进程,后台进程可以被其它进程命令临时打断并执行这个命令,比如我们输入ls指令,进程就会暂停并且输出Is的结果,但是最后需要自己把进程结束掉

Linux中,一次登陆中, 一个终端,一般会配上一个bash,每一个登陆,只允许一个进程是前台进程,可以允许多个进程是后台进程
当./process运行时,输入指令之所以不能运行就是因为此时的前台进程由bash转变为了process

  • 终端占用情况
    • 前台进程:会独占终端,直到进程执行完成或者被挂起,在这期间终端无法接受其他命令输入,用户只能与该进程进行交互。
    • 后台进程:不会占用终端,终端可以继续接受用户输入的其他命令,用户可以在同一个终端中同时启动多个后台进程,并随时切换到其他任务。
  • 运行特性
    • 前台进程:其执行过程会受到用户操作的直接影响,比如用户可以通过键盘输入来中断或暂停进程。如果终端关闭,前台进程通常会被终止,除非进行了特殊的设置。
    • 后台进程:通常是长时间运行的,不受终端关闭的影响,除非明确地对其进行停止或重启操作。它按照自身的逻辑和任务需求在后台持续运行,不会因为用户的一些常规操作而中断。

3.2 用户产生信号

  1. 键盘输入:用户可以通过在终端中按下特定的组合键来产生信号。例如:
    • Ctrl + C:产生 SIGINT 信号,用于中断当前正在运行的进程。比如,我们在终端中运行一个长时间运行的命令while true; do echo "Hello"; sleep 1; done,按下 Ctrl + C 后,该命令对应的进程会接收到 SIGINT 信号并终止。
    • Ctrl + \:产生 SIGQUIT 信号,不仅会终止进程,还会生成核心转储文件(如果系统配置允许,一般在云服务器上是默认关闭的,虚拟机上可能是开启的)。例如,运行一个简单的 C 程序#include <stdio.h> int main() { while(1); return 0; },编译运行后,按下 Ctrl + \,进程会终止并生成核心转储文件(在当前目录下,文件名为 core,具体名称和位置可能因系统配置而异)。(了解即可,这个生成core文件的内容与进程退出部分也有联系,有想了解的可以单独去搜索一下)
  1. 使用 kill 命令:用户可以使用 kill 命令向指定进程发送信号。kill 命令的基本语法是kill [信号编号] 进程ID。例如,要向进程 ID 为 1234 的进程发送 SIGTERM 信号(信号编号为 15),可以在终端中输入kill -15 1234,也可以使用信号名称kill -SIGTERM 1234。如果省略信号编号或名称,默认发送 SIGTERM 信号。

3.3 系统产生信号

  1. 进程异常:当进程发生异常时,如段错误(访问非法内存地址)、除零错误等,系统会向该进程发送相应的信号。
    • 段错误(Segmentation Fault):当进程访问了不属于它的内存区域时,会产生段错误,一般都是野指针问题,系统会向该进程发送 SIGSEGV 信号。例如,下面的 C 代码会导致段错误:
#include <stdio.h>int main() {int *ptr = NULL;*ptr = 10; // 试图向空指针指向的地址写入数据,会引发段错误return 0;}

编译运行这段代码,程序会崩溃,并提示 “Segmentation fault”,这是因为进程接收到了 SIGSEGV 信号。

  • 除零错误(Division by Zero):当进程执行除法运算时,如果除数为零,会产生除零错误,系统会向该进程发送 SIGFPE 信号。例如:
#include <stdio.h>int main()
{int a = 10;int b = 0;int c = a / b; // 除零操作,会引发除零错误return 0;
}

运行这段代码,程序会崩溃,并提示 “Floating point exception”,这是因为进程接收到了 SIGFPE 信号。

2. 系统资源相关:当系统资源达到一定阈值时,也可能产生信号。例如,当进程使用的内存超过了系统限制时,系统可能会发送 SIGKILL 信号来终止该进程,以防止系统内存耗尽。不过,这种情况通常需要系统进行相关的配置和监控。

3.4 软件产生信号

  1. 使用 kill 函数:在 C 语言编程中,可以使用 kill 函数向指定进程发送信号。kill 函数的原型可以用man手册查看,如下:
 man 2 kill

其中,pid 是目标进程的 ID,sig 是要发送的信号编号。例如,下面的代码演示了如何使用 kill 函数向另一个进程发送 SIGTERM 信号:

#include <stdio.h>
#include <sys/types.h>
#include <signal.h>
#include <unistd.h>
int main()
{pid_t target_pid = 1234; // 假设目标进程ID为1234int result = kill(target_pid, SIGTERM);if (result == -1){perror("kill failed");}else{printf("SIGTERM sent to process %d\n", target_pid);}return 0;
}

在实际使用中,需要将target_pid替换为真实的目标进程 ID。

2. 使用 raise 函数:进程可以使用 raise 函数向自身发送信号。raise 函数的原型也可以通过man手册来查看,如下:

man raise

其中,sig 是要发送的信号编号。例如,下面的代码演示了如何使用 raise 函数向自身发送 SIGINT 信号:

#include <stdio.h>
#include <signal.h>
int main()
{int result = raise(SIGINT);if (result != 0){perror("raise failed");}else{printf("SIGINT sent to self\n");}return 0;
}

运行这段代码,进程会接收到自己发送的 SIGINT 信号并终止。

四、信号的处理

4.1 默认处理方式

每个信号都有一个默认的处理方式,常见的默认处理方式包括:

  1. 终止进程:如 SIGINT、SIGTERM 等信号的默认处理方式是终止进程。
  1. 生成核心转储文件并终止进程:例如 SIGQUIT 信号,在终止进程的同时会生成核心转储文件,该文件包含了进程在收到信号时的内存状态等信息,可用于调试程序。
  1. 忽略信号:有些信号(如 SIGCHLD,子进程状态改变时发送给父进程的信号)的默认处理方式是忽略。

4.2 自定义信号处理函数

进程可以通过调用 signal 函数或 sigaction 函数来设置自定义的信号处理函数。

  1. signal 函数:signal 函数的原型如下:
man signal

其中,signum 是信号编号,handler 是指向信号处理函数的指针。例如,下面的代码演示了如何使用 signal 函数设置 SIGINT 信号的自定义处理函数:

#include <stdio.h>
#include <signal.h>
#include <unistd.h>
void signal_handler(int signum)
{printf("Received SIGINT. Cleaning up...\n");// 在这里进行一些清理工作,如关闭文件、释放资源等_exit(0); // 退出进程
}
int main()
{signal(SIGINT, signal_handler);while (1){printf("Running...\n");sleep(1);}return 0;
}

在这个例子中,当进程接收到 SIGINT 信号时,会调用signal_handler函数,而不是默认的终止进程操作。

2. sigaction 函数:sigaction 函数比 signal 函数提供了更丰富的功能,它可以设置信号处理函数、处理信号时的掩码、信号的标志等。sigaction 函数的原型如下:

#include <signal.h>int sigaction(int signum, const struct sigaction *act, struct sigaction *oldact);struct sigaction {void (*sa_handler)(int);void (*sa_sigaction)(int, siginfo_t *, void *);sigset_t sa_mask;int sa_flags;void (*sa_restorer)(void);};

其中,signum 是信号编号,act 是指向新的信号处理动作的结构体指针,oldact 是指向旧的信号处理动作的结构体指针(如果不需要获取旧的处理动作,可以设为 NULL)。例如,下面的代码演示了如何使用 sigaction 函数设置 SIGINT 信号的自定义处理函数:

#include <stdio.h>
#include <signal.h>
#include <unistd.h>
void signal_handler(int signum)
{printf("Received SIGINT. Cleaning up...\n");// 在这里进行一些清理工作,如关闭文件、释放资源等_exit(0); // 退出进程
}
int main()
{struct sigaction new_action, old_action;new_action.sa_handler = signal_handler;sigemptyset(&new_action.sa_mask);new_action.sa_flags = 0;sigaction(SIGINT, &new_action, &old_action);while (1){printf("Running...\n");sleep(1);}return 0;
}

这段代码与使用 signal 函数的例子功能类似,但使用 sigaction 函数可以更灵活地配置信号处理方式。

五、总结

信号是 Linux 系统中一种重要的进程间通信和异步事件通知机制。通过本文,我们详细了解了信号的概念,信号的产生和部分信号的处理工作,后面我们还会讲解信号的捕捉等处理工作,学习信号可以帮助我们更好的实现进程通信和异步处理等诸多操作

本篇笔记:


感谢各位大佬观看,创作不易,还请各位大佬点赞支持!!!

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

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

相关文章

海外问卷调查渠道查如何设置:最佳实践+示例

随着经济全球化和一体化进程的加速&#xff0c;企业间的竞争日益加剧&#xff0c;为了获得更大的市场份额&#xff0c;对企业和品牌而言&#xff0c;了解受众群体的的需求、偏好和痛点才是走向成功的关键。而海外问卷调查才是获得受众群体痛点的关键&#xff0c;制作海外问卷调…

《STL基础之vector、list、deque》

【vector、list、deque导读】vector、list、deque这三种序列式的容器&#xff0c;算是比较的基础容器&#xff0c;也是大家在日常开发中常用到的容器&#xff0c;因为底层用到的数据结构比较简单&#xff0c;笔者就将他们三者放到一起做下对比分析&#xff0c;介绍下基本用法&a…

一组开源、免费、Metro风格的 WPF UI 控件库

前言 今天大姚给大家分享一个开源、免费、Metro风格的 WPF UI 控件库&#xff1a;MahApps.Metro。 项目介绍 MahApps.Metro 是一个开源、免费、Metro风格的 WPF UI 控件库&#xff0c;提供了现代化、平滑和美观的控件和样式&#xff0c;帮助开发人员轻松创建具有现代感的 Win…

网易云音乐歌名可视化:词云生成与GitHub-Pages部署实践

引言 本文将基于前一篇爬取的网易云音乐数据, 利用Python的wordcloud、matplotlib等库, 对歌名数据进行深入的词云可视化分析. 我们将探索不同random_state对词云布局的影响, 并详细介绍如何将生成的词云图部署到GitHub Pages, 实现数据可视化的在线展示. 介绍了如何从原始数据…

通义灵码插件保姆级教学-IDEA(安装及使用)

一、JetBrains IDEA 中安装指南 官方下载指南&#xff1a;通义灵码安装教程-阿里云 步骤 1&#xff1a;准备工作 操作系统&#xff1a;Windows 7 及以上、macOS、Linux&#xff1b; 下载并安装兼容的 JetBrains IDEs 2020.3 及以上版本&#xff0c;通义灵码与以下 IDE 兼容&…

工业级 RAG 实现 - QAnything

文章目录 1. QAnything简介2. QAnything 安装教程2. 1 安装软件包2.2 运行QAnything框架2.3 访问前端页面 3. QAnything 简单使用3.1 创建知识库3.2 创建聊天机器人3.3 关联知识库3.4 测试 4. QAnything 的分析&#xff1a;4. 1 QAnything 架构4. 2 两阶段检索4. 2.1 一阶段检索…

Cross-Resolution知识蒸馏论文学习

TPAMI 2024&#xff1a;Pixel Distillation: Cost-Flexible Distillation Across Image Sizes and Heterogeneous Networks 教师模型使用高分辨率输入进行学习&#xff0c;学生模型使用低分辨率输入进行学习 学生蒸馏损失&#xff1a;Lpkd和Lisrd Lpkd&#xff1a;任务损失lo…

Versal - 基础3(AXI NoC 专题+仿真+QoS)

目录 1. 简介 2. 示例 2.1 示例说明 2.2 创建项目 2.2.1 平台信息 2.2.2 AXI NoC Automation 2.2.3 创建时钟和复位 2.3 配置 NoC 2.4 配置 AXI Traffic 2.5 配置 Memory Size 2.6 Validate BD 2.7 添加观察信号 2.8 运行仿真 2.9 查看结果 2.9.1 整体波形 2.9…

【PostgreSQL内核学习 —— (WindowAgg(一))】

WindowAgg 窗口函数介绍WindowAgg理论层面源码层面WindowObjectData 结构体WindowStatePerFuncData 结构体WindowStatePerAggData 结构体eval_windowaggregates 函数update_frameheadpos 函数 声明&#xff1a;本文的部分内容参考了他人的文章。在编写过程中&#xff0c;我们尊…

RubyFPV开源代码之系统简介

RubyFPV开源代码之系统简介 1. 源由2. 工程架构3. 特性介绍&#xff08;软件&#xff09;3.1 特性亮点3.2 数字优势3.3 使用功能 4. DEMO推荐&#xff08;硬件&#xff09;4.1 天空端4.2 地面端4.3 按键硬件Raspberry PiRadxa 3W/E/C 5. 软件设计6. 参考资料 1. 源由 RubyFPV以…

MySQL(单表访问)

今天是新年&#xff0c;祝大家新年快乐&#xff0c;但是生活还是得继续。 后面也会持续更新&#xff0c;学到新东西会在其中补充。 建议按顺序食用&#xff0c;欢迎批评或者交流&#xff01; 缺什么东西欢迎评论&#xff01;我都会及时修改的&#xff01; 大部分截图和文章采…

汇编的使用总结

一、汇编的组成 1、汇编指令&#xff08;指令集&#xff09; 数据处理指令: 数据搬移指令 数据移位指令 位运算指令 算术运算指令 比较指令 跳转指令 内存读写指令 状态寄存器传送指令 异常产生指令等 2、伪指令 不是汇编指令&#xff0c;但是可以起到指令的作用&#xff0c;伪…

汇编基础语法及其示例

1.汇编指令 1.1汇编指令的基本格式 <opcode>{<cond>}{s} <Rd> , <Rn> , <shifter_operand> <功能码>{<条件码>}{cpsr影响位} <目标寄存器> , <第一操作寄存器> , <第二操作数> 注&#xff1a;第一操作寄存器…

FLTK - FLTK1.4.1 - 搭建模板,将FLTK自带的实现搬过来做实验

文章目录 FLTK - FLTK1.4.1 - 搭建模板&#xff0c;将FLTK自带的实现搬过来做实验概述笔记my_fltk_test.cppfltk_test.hfltk_test.cxx用adjuster工程试了一下&#xff0c;好使。END FLTK - FLTK1.4.1 - 搭建模板&#xff0c;将FLTK自带的实现搬过来做实验 概述 用fluid搭建UI…

基于物联网设计的疫苗冷链物流监测系统

一、前言 1.1 项目开发背景 随着全球经济的发展和物流行业的不断创新&#xff0c;疫苗和生物制品的运输要求变得越来越高。尤其是疫苗的冷链物流&#xff0c;温度、湿度等环境因素的控制直接关系到疫苗的质量和效力&#xff0c;因此高效、可靠的冷链监控系统显得尤为重要。冷…

JVM对象分配内存如何保证线程安全?

大家好&#xff0c;我是锋哥。今天分享关于【JVM对象分配内存如何保证线程安全?】面试题。希望对大家有帮助&#xff1b; JVM对象分配内存如何保证线程安全? 1000道 互联网大厂Java工程师 精选面试题-Java资源分享网 在JVM中&#xff0c;对象的内存分配是通过堆内存进行的。…

移动光猫怎么自己改桥接模式?

环境&#xff1a; 型号H3-8s 问题描述&#xff1a; 家里宽带用的是H3-8s 光猫&#xff0c;想改桥接模式。 解决方案&#xff1a; 1.默认管理员账号和密码&#xff1a; 账号&#xff1a;CMCCAdmin 密码&#xff1a;aDm8H%MdAWEB页面我试了登陆不了&#xff0c;显示错误 …

大数据Hadoop入门3

第五部分&#xff08;Apache Hive DML语句和函数使用&#xff09; 1.课程内容大纲和学习目标 2.Hive SQL-DML-load加载数据操作 下面我们随机创建文件尝试一下 先创建一个hivedata文件夹 在这个文件夹中写一个1.txt文件 下面使用beeline创建一张表 只要将1.txt文件放在t_1文件…

2025.1.26机器学习笔记:C-RNN-GAN文献阅读

2025.1.26周报 文献阅读题目信息摘要Abstract创新点网络架构实验结论缺点以及后续展望 总结 文献阅读 题目信息 题目&#xff1a; C-RNN-GAN: Continuous recurrent neural networks with adversarial training会议期刊&#xff1a; NIPS作者&#xff1a; Olof Mogren发表时间…

基于物联网的火灾报警器设计与实现(论文+源码)

1 总体方案设计 本次基于物联网的火灾报警器&#xff0c;其系统总体架构如图2.1所示&#xff0c;采用STM32f103单片机作为控制器&#xff0c;通过DS18B20传感器实现温度检测&#xff1b;通过MQ-2烟雾传感器实现烟雾检测&#xff1b;.通过火焰传感器实现火焰检测&#xff0c;当…