Linux 进程信号的产生
目录
0.前言
1. 通过终端按键产生信号
1.1 Ctrl+C:发送 SIGINT 信号
1.2 Ctrl+\:发送 SIGQUIT 信号
1.3 Ctrl+Z:发送 SIGTSTP 信号
2.调用系统命令向进程发信号
3.使用函数产生信号
3.1 kill 函数
3.2 raise 函数
3.3 abort 函数
4.由软件条件产生信号
4.1 SIGPIPE 信号
4.2 SIGALRM 信号
5.硬件异常产生信号
5.1 常见硬件异常信号
5.1.1 除 0 操作:SIGFPE 信号
5.1.2 访问野指针:SIGSEGV 信号
5.2 核心转储(Core Dump)
6.小结
(图像由AI生成)
0.前言
在 Linux 系统中,信号是用于进程间通信的重要机制,通过信号可以实现对进程的控制、状态传递以及异常处理。在上一篇博客中,我们简单介绍了进程信号的概念、常见类型以及信号的基本作用。本篇博客将继续深入,从信号的产生开始,探讨信号如何被触发并送达进程。这是理解信号处理的第一步,也是后续学习信号保存和信号处理机制的基础。通过本篇内容,你将了解信号的几种常见触发方式,包括用户手动产生、程序主动触发,以及系统自动生成等场景。
1. 通过终端按键产生信号
Linux 系统中,终端不仅是与操作系统交互的重要工具,也是信号产生的主要入口之一。在终端中按下特定的键盘组合,可以向当前前台进程发送信号,这些信号可以中断、暂停或终止程序运行。
1.1 Ctrl+C:发送 SIGINT 信号
-
概念
按下Ctrl+C
会向当前前台进程发送SIGINT
信号(Signal Interrupt)。这是用户最常用的中断方式,用于优雅地终止正在运行的程序。 -
默认行为
程序收到SIGINT
信号后,默认会立即终止执行,但不会生成核心转储文件。 -
实际场景
例如,当你运行一个死循环脚本时,可以通过Ctrl+C
终止它:while true; do echo "Running..."; sleep 1; done
按下
Ctrl+C
后,循环将中止。 -
自定义处理
程序也可以捕获SIGINT
信号并定义自定义逻辑。例如,以下代码展示了如何拦截并处理SIGINT
信号:#include <stdio.h> #include <signal.h>void handle_sigint(int sig) {printf("Caught SIGINT signal: %d\n", sig); }int main() {signal(SIGINT, handle_sigint);while (1) {printf("Running... Press Ctrl+C to interrupt\n");sleep(1);}return 0; }
1.2 Ctrl+\:发送 SIGQUIT 信号
-
概念
按下Ctrl+\
会触发SIGQUIT
信号(Signal Quit)。与SIGINT
类似,SIGQUIT
的默认行为也是终止进程,但它会额外生成一个核心转储文件(core dump)。 -
默认行为
程序收到SIGQUIT
信号后,系统会记录程序运行时的内存状态,生成 core dump 文件,供开发者调试使用。 -
实际场景
在程序运行时按下Ctrl+\
,程序不仅会终止,还会留下 core dump 文件。如果 core dump 未启用,可以通过以下命令启用:ulimit -c unlimited # 设置核心文件大小为无限
1.3 Ctrl+Z:发送 SIGTSTP 信号
-
概念
按下Ctrl+Z
会向前台进程发送SIGTSTP
信号(Signal Terminal Stop)。该信号用于将进程挂起(暂停运行),并将控制权还给终端。 -
默认行为
收到SIGTSTP
信号后,进程会进入“暂停”状态,直到用户手动恢复它。恢复命令包括:fg
:恢复进程到前台继续执行。bg
:将进程移至后台继续执行。
-
实际场景
当运行一个耗时较长的任务时,可以按Ctrl+Z
暂时挂起它,进行其他操作。例如:sleep 100
按下
Ctrl+Z
后,任务将暂停。输入fg
恢复它,或者使用bg
将其移至后台。
2.调用系统命令向进程发信号
在 Linux 系统中,除了通过终端按键,用户还可以使用系统命令向进程发送信号。其中最常用的命令是 kill
,它允许用户直接向目标进程发送指定信号,以控制或终止进程。kill
命令的基本语法如下:
kill [选项] <进程ID>
常用选项
-SIGNAL
:指定发送的信号名称或编号。例如,-SIGKILL
或-9
表示发送SIGKILL
信号。-l
:列出所有信号名称及其编号。-s SIGNAL
:显式指定信号名称。-pid
:目标进程 ID,可以是一个或多个。
举例说明
-
发送默认信号(SIGTERM)
kill 1234(某个进程的PID)
默认发送
SIGTERM
信号,通常用于优雅地终止进程。 -
发送特定信号
强制终止进程可以使用SIGKILL
(信号编号9
):kill -9 1234
-
列出所有信号
查看系统支持的信号列表:kill -l
3.使用函数产生信号
3.1 kill 函数
kill
是用于向任意进程发送信号的系统调用,其语法如下:
#include <sys/types.h>
#include <signal.h>int kill(pid_t pid, int sig);
-
参数说明:
pid
:目标进程的 PID。> 0
:向指定的单个进程发送信号。= 0
:向调用进程所在的进程组发送信号。< -1
:向特定进程组发送信号。
sig
:要发送的信号类型(如SIGINT
或SIGKILL
)。
-
示例: 向当前进程发送
SIGTERM
信号:#include <signal.h> #include <unistd.h>int main() {kill(getpid(), SIGTERM);return 0; }
3.2 raise 函数
raise
是一个标准库函数,用于向自身发送信号,其本质是对 kill
函数的封装。语法如下:
#include <signal.h>int raise(int sig);
-
参数说明:
sig
:要发送的信号。
-
特点:
- 只能向当前进程发送信号。
- 使用方便,不需要获取 PID。
-
示例: 触发
SIGINT
信号:#include <signal.h> #include <stdio.h>void signal_handler(int sig) {printf("Caught signal: %d\n", sig); }int main() {signal(SIGINT, signal_handler); // 注册信号处理函数raise(SIGINT); // 发送信号return 0; }
3.3 abort 函数
abort
是一个标准库函数,用于向自身发送 SIGABRT
信号,强制使程序异常终止,并生成核心转储文件(core dump)。语法如下:
#include <stdlib.h>void abort(void);
-
特点:
- 触发
SIGABRT
信号。 - 通常用于在程序遇到严重错误时调用。
- 如果未捕获
SIGABRT
,程序将直接退出。
- 触发
-
示例: 强制终止程序并生成 core dump:
#include <stdlib.h>int main() {abort();return 0; }
4.由软件条件产生信号
除了用户手动触发信号和程序显式调用信号函数外,信号也可以在程序运行时,由特定的软件条件自动触发。例如,管道写入异常会触发 SIGPIPE
信号,定时器到期会触发 SIGALRM
信号。
4.1 SIGPIPE 信号
-
触发条件
当一个进程尝试向已经关闭的管道(pipe)或套接字(socket)写入数据时,系统会自动发送SIGPIPE
信号。默认行为是终止进程。 -
常见场景
例如,父进程向关闭的管道写入数据:#include <unistd.h> #include <signal.h> #include <stdio.h>int main() {int fds[2];pipe(fds); // 创建管道close(fds[0]); // 关闭读端if (write(fds[1], "data", 4) == -1) { // 写入数据perror("write error");}return 0; }
输出类似:
write error: Broken pipe
-
解决方式
捕获SIGPIPE
信号并进行自定义处理,或者忽略该信号:signal(SIGPIPE, SIG_IGN); // 忽略SIGPIPE
4.2 SIGALRM 信号
-
触发条件
SIGALRM
信号由alarm
函数触发,用于在指定的时间间隔后通知进程执行某些任务。 -
alarm
函数alarm
函数设置一个秒级定时器,到期时发送SIGALRM
信号:#include <unistd.h>unsigned int alarm(unsigned int seconds);
-
示例
设置一个 3 秒定时器,触发后执行信号处理函数:#include <signal.h> #include <unistd.h> #include <stdio.h>void handle_alarm(int sig) {printf("Alarm triggered!\n"); }int main() {signal(SIGALRM, handle_alarm); // 注册处理函数alarm(3); // 设置定时器pause(); // 等待信号return 0; }
输出类似:
Alarm triggered!
-
取消定时器
再次调用alarm
函数,传入0
即可取消定时器:alarm(0);
5.硬件异常产生信号
在程序运行过程中,某些硬件异常(例如非法操作或内存访问)会触发系统向进程发送特定信号。这些信号通常表示程序存在错误,默认行为是终止程序运行,并可能生成 核心转储文件(core dump)。
5.1 常见硬件异常信号
5.1.1 除 0 操作:SIGFPE 信号
-
触发条件
当程序执行非法的算术运算(如整数除以 0)时,会触发SIGFPE
信号(Floating Point Exception)。默认行为是终止进程。 -
示例代码
以下代码试图执行除以 0 的操作:#include <stdio.h>int main() {int a = 1;int b = 0;printf("%d\n", a / b); // 除以 0return 0; }
结果:程序崩溃,触发
SIGFPE
。 -
捕获信号
使用信号处理函数捕获SIGFPE
:#include <signal.h> #include <stdio.h>void handle_sigfpe(int sig) {printf("Caught SIGFPE: Illegal operation\n"); }int main() {signal(SIGFPE, handle_sigfpe);int a = 1, b = 0;printf("%d\n", a / b);return 0; }
5.1.2 访问野指针:SIGSEGV 信号
-
触发条件
当程序尝试访问非法内存地址(如空指针或已释放的内存)时,会触发SIGSEGV
信号(Segmentation Fault)。默认行为是终止进程。 -
示例代码
以下代码访问了一个空指针:#include <stdio.h>int main() {int *ptr = NULL;*ptr = 42; // 访问空指针return 0; }
结果:程序崩溃,触发
SIGSEGV
。 -
捕获信号
可以捕获SIGSEGV
信号来处理异常:#include <signal.h> #include <stdio.h>void handle_sigsegv(int sig) {printf("Caught SIGSEGV: Invalid memory access\n"); }int main() {signal(SIGSEGV, handle_sigsegv);int *ptr = NULL;*ptr = 42;return 0; }
5.2 核心转储(Core Dump)
核心转储是一种调试工具,用于记录程序崩溃时的内存状态,帮助开发者排查问题。
生成核心转储
-
启用核心转储
默认情况下,核心转储可能被限制或禁用。可以使用以下命令启用:ulimit -c unlimited
-
运行出错程序
当程序崩溃时,系统会生成核心转储文件,通常命名为core
或core.<pid>
。 -
调试核心转储
使用调试工具gdb
分析核心转储文件:gdb ./program core
在调试器中,可以查看崩溃时的调用堆栈和内存状态。
示例调试
假设程序崩溃生成了核心转储文件,可以通过以下命令进入调试器:
gdb ./a.out core
进入调试器后,运行 bt
(backtrace)命令查看调用堆栈:
bt (进入gdb调试后)
6.小结
本篇博客全面介绍了 Linux 系统中信号的产生方式,从终端按键、系统命令,到函数调用和软件条件触发,再到硬件异常的信号处理。信号作为进程间通信和异常管理的关键机制,贯穿了用户操作、程序设计和系统运行的各个层面。理解信号的来源和触发方式,是深入学习 Linux 信号处理与调试技巧的重要基础,为编写健壮的程序提供了强有力的支持。
相关文章:

Linux 进程信号的产生
目录 0.前言 1. 通过终端按键产生信号 1.1 CtrlC:发送 SIGINT 信号 1.2 Ctrl\:发送 SIGQUIT 信号 1.3 CtrlZ:发送 SIGTSTP 信号 2.调用系统命令向进程发信号 3.使用函数产生信号 3.1 kill 函数 3.2 raise 函数 3.3 abort 函数 4.由软件条件产…...

CentOS8 在MySQL8.0 实现半同步复制
#原理 MySQL默认是异步的,不要求必须全部同步到从节点才返回成功结果; 同步复制: 用户发请求到代理, 代理收到请求后写/更新数据库写入到二进制日志bin_log, 然后必须等数据发到所有的从节点, 从节点全部收到数据后, 主节点才返回给客户端的成功结果。 弊端: 客…...

数据分析——Python绘制实时的动态折线图
最近在做视觉应用开发,有个需求需要实时获取当前识别到的位姿点位是否有突变,从而确认是否是视觉算法的问题,发现Python的Matplotlib进行绘制比较方便。 目录 1.数据绘制2.绘制实时的动态折线图3.保存实时数据到CSV文件中 import matplotlib.…...

【Redis】Redis的一些应用场景及使用策略
应用的场景 Redis 是一个高性能的内存数据库,广泛用于各种应用场景,以下是一些常见的应用场景: 缓存:Redis 的高读写性能使其非常适合作为缓存层,存储频繁访问的数据以减少数据库负载和加快响应时间。例如,…...

CentOS 8 安装 chronyd 服务
操作场景 目前原生 CentOS 8 不支持安装 ntp 服务,因此会发生时间不准的问题,需使用 chronyd 来调整时间服务。CentOS 8以及 TencentOS 3.1及以上版本的实例都使用 chronyd 服务实现时钟同步。本文介绍了如何在 CentOS 8 操作系统的腾讯云服务器上安装并…...

HarmonyOS ArkUI(基于ArkTS) 常用组件
一 Button 按钮 Button是按钮组件,通常用于响应用户的点击操作,可以加子组件 Button(我是button)Button(){Text(我是button)}type 按钮类型 Button有三种可选类型,分别为胶囊类型(Capsule)、圆形按钮(Circle…...

不用来回切换,一个界面管理多个微信
你是不是也有多个微信号需要管理? 是不是也觉得频繁切换账号很麻烦? 是不是也想提升多账号管理的效率? 在工作中,好的辅助工具,能让我们的效率加倍增长! 今天, 就给大家分享一个多微管理工具…...

MySQL系统优化
文章目录 MySQL系统优化第一章:引言第二章:MySQL服务架构优化1. 读写分离2. 水平分区与垂直分区3. 缓存策略 第三章:MySQL配置优化1. 内存分配优化Buffer Pool 的优化查询缓存与表缓存Key Buffer 2. 连接优化最大连接数会话超时连接池 3. 日志…...

若依笔记(八):芋道的Docker容器化部署
目录 增加环境变量 DockerFile与镜像制作 nginx配置 vue3前端工程 首先搞个ECS阿里主机,1核4g足够,最大程度保证是docker运行来减少主机资源占用,同时因为是公有云,端口策略安全很重要,每个对外服务的端口要通过安全组放开; mysql的docker使用8版本,启动时候给my.cn…...

前端隐藏元素的方式有哪些?HTML 和 CSS 中隐藏元素的多种方法
当面试官突然问你:“前端隐藏元素的方式有哪些?”你还是只知道 display: none 吗? 其实,在前端开发的世界里,隐藏元素的方法非常多。每种方法都有自己的小技巧和使用场景,了解它们不仅能让你应对自如&…...

sqli—labs靶场 5-8关 (每日4关练习)持续更新!!!
Less-5 上来先进行查看是否有注入点,判断闭合方式,查询数据列数,用union联合注入查看回显位,发现到这一步的时候,和前四道题不太一样了,竟然没有回显位??? 我们看一下源…...

【Java】异常处理实例解析
文章目录 Java异常处理实例解析Example01_2023yang:未处理的异常Example02_2023yang:捕获并处理异常Example03_2023yang:finally块的使用Example04_2023yang:自定义异常Example05_2023yang:忽略异常信息Example06_2023…...

flutter调试
上面的调试The following FormatException was thrown while handling a gesture: Invalid double -Infinity874When the exception was thrown, this was the stack: #0 double.parse (dart:core-patch/double_patch.dart:113:28) #1 _CalculatorScreenState._butt…...

使用Web Workers提升JavaScript的并行处理能力
💓 博客主页:瑕疵的CSDN主页 📝 Gitee主页:瑕疵的gitee主页 ⏩ 文章专栏:《热点资讯》 使用Web Workers提升JavaScript的并行处理能力 使用Web Workers提升JavaScript的并行处理能力 使用Web Workers提升JavaScript的…...

【含开题报告+文档+PPT+源码】基于Spring Boot智能综合交通出行管理平台的设计与实现
开题报告 随着城市规模的不断扩大和交通拥堵问题的日益严重,综合交通出行管理平台的研究与实现显得尤为重要。现代城市居民对于出行的需求越来越多样化,对于交通信息的获取和处理能力也提出了更高的要求。传统的交通管理方式已经难以满足这些需求&#…...

STM32寄存器结构体详解
一、寄存器结构体详解 对于STM32而言,使用一个结构体将一个外设的所有寄存器都放到一起 二、修改驱动 1、添加清除bss段代码 2、添加寄存器结构体 在寄存器结构体中添加寄存器的时候一定要注意地址的连续性,如果地址不连续的话,要添加占位…...

如何建立devops?
要建立DevOps系统,可以遵循以下步骤: 一、明确目标与确立原则 明确目标:确定DevOps系统的总体目标,例如提高软件发布频率、缩短反馈时间、提升软件质量等。确立原则:确立DevOps的核心原则,包括持续集成&a…...

shell基础(3)
声明! 学习视频来自B站up主 **泷羽sec** 有兴趣的师傅可以关注一下,如涉及侵权马上删除文章,笔记只是方便各位师傅的学习和探讨,文章所提到的网站以及内容,只做学习交流,其他均与本人以及泷羽sec团…...

2024年11月16日Github流行趋势
项目名称:opendatalab / MinerU 项目维护者:myhloli, dt-yy, Focusshang, drunkpig, papayalove等项目介绍:一站式开源高质量数据提取工具,支持PDF/网页/多格式电子书提取。项目star数:16,398项目fork数:1,…...

k8s更新
k8s更新 1.30 升级了 Metrics Server 到 v0.7.0 kubectl get cronjob命令增加了时区列显示 kubectl describe命令在描述VolumeAttributesClass、作业、Pod 模板等时提供了更多信息,有助于深入排查问题。 改进了kubectl logs命令,当 Pod 未找到时会显示所…...

ES6进阶知识一
目录 一、ES6构建工具与模块化 1.1.构建工具 1.1.1.Webpack 安装 Webpack 配置 Webpack 使用 Webpack 1.1.2.Babel 安装 Babel 配置 Babel 1.2.ES6模块化 1.命名导出导入 导出模块 导入模块 2. 默认导出与导入 导出模块 导入模块 1.3.完整案例展示 1. 项目结构…...

C#/WinForm拖拽文件上传
一、首先创建一个上传文件的类,继承Control类,如下: public class UploadControl : Control{private Image _image;public UploadControl(){this.SetStyle(ControlStyles.UserPaint | //控件自行绘制,而不使用操作系统的绘制Cont…...

IT运维的365天--019 用php做一个简单的文件上传工具
前情提要:朋友的工作室,有几个网站分布在不同的服务器上,要经常进行更新,之前是手动复制压缩包到各个服务器去更新(有写了自动更新的Shell脚本)。但还是觉得太麻烦,每次还要手动传输压缩包到各个…...

详细的oracle rac维护命令集合
一、查看命令 所有实例和服务的状态 $srvctl status database -d orcl Instance orcl1 is running on node db1 Instance orcl2 is running on node db2 单个实例的状态 $ srvctl status instance -d orcl -i orcl2 Instance orcl2 is running on node db2 单个节点的应用程序…...

23 种设计模式详解
设计模式的分类 总体来说设计模式分为三大类: 创建型模式,共五种:单例模式、工厂方法模式、抽象工厂模式、建造者模式、原型模式。 结构型模式,共七种:适配器模式、装饰器模式、代理模式、外观模式、桥接模式、 组合模…...

Python毕业设计选题:基于django+vue的二手物品交易系统
开发语言:Python框架:djangoPython版本:python3.7.7数据库:mysql 5.7数据库工具:Navicat11开发软件:PyCharm 系统展示 管理员登录 管理员功能界面 用户管理 店铺管理 二手物品管理 广告管理 留言反馈 订单…...

VMware 17虚拟Ubuntu 22.04设置共享目录
VMware 17虚拟Ubuntu 22.04设置共享目录 共享文件夹挂载命令!!!<font colorred>配置启动自动挂载Chapter1 VMware 17虚拟Ubuntu 22.04设置共享目录一、卸载老版本二、安装open-vm-tools<font colorred>三、配置启动自动挂载四、添…...

Rust学习(五):泛型、trait
Rust学习(五):泛型、trait 1、泛型: 相信小伙伴们一定还记得,之前我们实现了一个add函数,并指定了参数类型为:i32: fn add(x:i32, y:i32) ->i32 {x y }这里我们就会遇到一个问…...

智能零售柜商品识别
项目源码获取方式见文章末尾! 600多个深度学习项目资料,快来加入社群一起学习吧。 《------往期经典推荐------》 项目名称 1.【基于CNN-RNN的影像报告生成】 2.【卫星图像道路检测DeepLabV3Plus模型】 3.【GAN模型实现二次元头像生成】 4.【CNN模型实现…...

2024智能机器人与自动控制国际学术会议 (IRAC 2024)
主办,承办,支持单位 会议官网 www.icirac.org 大会时间:2024年11月29-12月1日 大会简介 2024智能机器人与自动控制国际学术会议 (IRAC 2024)由华南理工大学主办,会议将于2024年11月29日-12月1日在中国广…...