当前位置: 首页 > news >正文

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:要发送的信号类型(如 SIGINTSIGKILL)。
  • 示例: 向当前进程发送 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)

核心转储是一种调试工具,用于记录程序崩溃时的内存状态,帮助开发者排查问题。

生成核心转储

  1. 启用核心转储
    默认情况下,核心转储可能被限制或禁用。可以使用以下命令启用:

    ulimit -c unlimited
  2. 运行出错程序
    当程序崩溃时,系统会生成核心转储文件,通常命名为 corecore.<pid>

  3. 调试核心转储
    使用调试工具 gdb 分析核心转储文件:

    gdb ./program core

    在调试器中,可以查看崩溃时的调用堆栈和内存状态。

示例调试

假设程序崩溃生成了核心转储文件,可以通过以下命令进入调试器:

gdb ./a.out core

进入调试器后,运行 bt(backtrace)命令查看调用堆栈:

bt (进入gdb调试后)

6.小结

本篇博客全面介绍了 Linux 系统中信号的产生方式,从终端按键、系统命令,到函数调用和软件条件触发,再到硬件异常的信号处理。信号作为进程间通信和异常管理的关键机制,贯穿了用户操作、程序设计和系统运行的各个层面。理解信号的来源和触发方式,是深入学习 Linux 信号处理与调试技巧的重要基础,为编写健壮的程序提供了强有力的支持。

相关文章:

Linux 进程信号的产生

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

CentOS8 在MySQL8.0 实现半同步复制

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

数据分析——Python绘制实时的动态折线图

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

【Redis】Redis的一些应用场景及使用策略

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

CentOS 8 安装 chronyd 服务

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

HarmonyOS ArkUI(基于ArkTS) 常用组件

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

不用来回切换,一个界面管理多个微信

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

MySQL系统优化

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

若依笔记(八):芋道的Docker容器化部署

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

前端隐藏元素的方式有哪些?HTML 和 CSS 中隐藏元素的多种方法

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

sqli—labs靶场 5-8关 (每日4关练习)持续更新!!!

Less-5 上来先进行查看是否有注入点&#xff0c;判断闭合方式&#xff0c;查询数据列数&#xff0c;用union联合注入查看回显位&#xff0c;发现到这一步的时候&#xff0c;和前四道题不太一样了&#xff0c;竟然没有回显位&#xff1f;&#xff1f;&#xff1f; 我们看一下源…...

【Java】异常处理实例解析

文章目录 Java异常处理实例解析Example01_2023yang&#xff1a;未处理的异常Example02_2023yang&#xff1a;捕获并处理异常Example03_2023yang&#xff1a;finally块的使用Example04_2023yang&#xff1a;自定义异常Example05_2023yang&#xff1a;忽略异常信息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的并行处理能力

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

【含开题报告+文档+PPT+源码】基于Spring Boot智能综合交通出行管理平台的设计与实现

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

STM32寄存器结构体详解

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

如何建立devops?

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

shell基础(3)

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

2024年11月16日Github流行趋势

项目名称&#xff1a;opendatalab / MinerU 项目维护者&#xff1a;myhloli, dt-yy, Focusshang, drunkpig, papayalove等项目介绍&#xff1a;一站式开源高质量数据提取工具&#xff0c;支持PDF/网页/多格式电子书提取。项目star数&#xff1a;16,398项目fork数&#xff1a;1,…...

k8s更新

k8s更新 1.30 升级了 Metrics Server 到 v0.7.0 kubectl get cronjob命令增加了时区列显示 kubectl describe命令在描述VolumeAttributesClass、作业、Pod 模板等时提供了更多信息&#xff0c;有助于深入排查问题。 改进了kubectl logs命令&#xff0c;当 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拖拽文件上传

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

IT运维的365天--019 用php做一个简单的文件上传工具

前情提要&#xff1a;朋友的工作室&#xff0c;有几个网站分布在不同的服务器上&#xff0c;要经常进行更新&#xff0c;之前是手动复制压缩包到各个服务器去更新&#xff08;有写了自动更新的Shell脚本&#xff09;。但还是觉得太麻烦&#xff0c;每次还要手动传输压缩包到各个…...

详细的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 种设计模式详解

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

Python毕业设计选题:基于django+vue的二手物品交易系统

开发语言&#xff1a;Python框架&#xff1a;djangoPython版本&#xff1a;python3.7.7数据库&#xff1a;mysql 5.7数据库工具&#xff1a;Navicat11开发软件&#xff1a;PyCharm 系统展示 管理员登录 管理员功能界面 用户管理 店铺管理 二手物品管理 广告管理 留言反馈 订单…...

VMware 17虚拟Ubuntu 22.04设置共享目录

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

Rust学习(五):泛型、trait

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

智能零售柜商品识别

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

2024智能机器人与自动控制国际学术会议 (IRAC 2024)

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