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

Linux信号入门

目录

一、生活中的信号:你的快递到了!

二、技术视角:Ctrl-C背后的魔法

三、深入信号世界

1. 信号身份证

2. 信号记录原理

3. 信号三处理法


一、生活中的信号:你的快递到了!

        想象你在网上疯狂购物后,等待不同快递送货的场景。这个过程中蕴含着与计算机信号处理惊人相似的逻辑:

  1. 识别快递:尽管快递尚未抵达,但你清楚地知道,当快递到达时,你需要采取相应的行动,这便是你能够“识别快递”。(就像进程知道如何处理信号)

  2. 延迟处理:当快递员将快递送到楼下并通知你时,你正在忙于游戏,需要5分钟后才能去取快递。在这5分钟内,你虽未立即取快递,但已知晓有快递到来,这就是“延迟处理”。(信号可被暂存不立即处理)

  3. 记忆机制:从收到通知到拿到快递这段时间,你记住了有快递要取,这便是信号的“记忆机制”。(信号被操作系统记录)

  4. 处理方式:当你时间合适,顺利拿到快递后,便要开始处理快递,处理方式通常有三种:

    • ✅ 默认操作:开心地打开快递使用商品(默认处理

    • 🎁 自定义操作:将零食快递送给女朋友(自定义处理

    • 🗑️ 忽略操作:将快递扔在床头继续游戏(忽略信号

整个快递到来的过程对你而言是异步的,你无法准确预知快递员何时会打电话。

二、技术视角:Ctrl-C背后的魔法

        在技术领域,信号是进程间事件异步通知的一种方式,属于软中断。观察下面这个典型的无限循环程序:

#include <stdio.h>
#include <unistd.h>

int main()
{
    while(1){
        printf("hello signal!\n");
        sleep(1);
    }
    return 0;
}

        当程序运行时,该程序会陷入死循环,不断打印"hello signal!"。要终止这种死循环,通常使用Ctrl+C。当用户按下Ctrl+C时,键盘输入会产生一个硬中断,操作系统获取并将其解释为信号(Ctrl+C对应2号信号),随后将2号信号发送给目标前台进程,前台进程收到2号信号后便会退出。

        为了证明进程收到Ctrl+C时确实收到了2号信号,可以使用signal()函数进行信号捕捉实验。这个系统调用的原型为:

void (*signal(int sig, void (*handler)(int)))(int);
  • 参数1:指定要捕捉的信号编号(如2号信号)

  • 参数2:定义处理函数(参数为信号值,无返回值)

  • 返回值:原信号处理函数指针

#include <unistd.h>
#include <stdio.h>
#include <signal.h>

void handler(int sig)
{
    // 注意:此处仅演示信号捕捉,实际应避免在信号处理函数中使用printf等非异步安全函数
    printf("捕获到%d号信号!\n", sig);
}

int main()
{
    signal(SIGINT, handler);//注册2号信号处理

    while(1)
    {
        printf("hello signal!\n");
        sleep(1);
    }

    return 0;
}

        运行改造后的程序时,每次按下Ctrl+C,不会再直接终止进程,而会立即执行handler函数,输出"捕获到2号信号!",然后程序继续执行循环。


🍇下面我们将生活例子和 Ctrl-C 信号处理过程相结合,来解释一下信号处理过程:

生活例子引入:

        假设你是一个忙碌的进程,正在执行一项任务,比如写作业。操作系统是快递员,负责给你传递各种消息。信号就像是快递员送来的不同类型的快递。当快递员(操作系统)给你送来一个快递(信号)时,你需要决定如何处理它:是立即停下手中的活去处理快递,还是稍后再处理,或者直接拒收。

信号处理过程:

  1. 信号产生:当用户按下 Ctrl-C 键时,终端会生成一个中断信号(SIGINT),这个信号会被发送给当前正在运行的进程。

  2. 信号传递:操作系统(内核)捕捉到这个信号后,会暂停进程的当前执行,并将信号传递给该进程。

  3. 信号处理

    • 默认处理:如果进程没有对 SIGINT 信号进行特殊处理,操作系统会执行默认动作,通常是终止进程。

    • 自定义处理:如果进程安装了信号处理函数(比如通过 signal 或 sigaction 函数),操作系统会将控制权转交给该处理函数,执行用户自定义的代码来处理信号。

  4. 恢复执行:信号处理完成后,操作系统会恢复进程的执行,继续执行被中断的代码。

与生活例子的结合:

  • 快递(信号)的产生:就像有人给你下单寄了一个快递,快递员(操作系统)会收到这个任务。

  • 快递(信号)的传递:快递员会把快递送到你的手中,这相当于操作系统将信号传递给进程。

  • 处理快递(信号)

    • 如果你没有特别说明如何处理快递(没有安装信号处理函数),快递员可能会直接把快递放在门口(默认处理),比如当你收到一个“停止”信号时,你停止当前活动。

    • 如果你提前告诉快递员如何处理快递(安装了信号处理函数),比如“请把快递放在桌子上”,快递员会按照你的要求去做,这相当于进程执行自定义的信号处理函数。

  • 恢复活动(恢复执行):处理完快递后,你可以继续做之前的事情,就像进程在处理完信号后继续执行后续的代码。


🌴注意事项:

  1. 信号发送对象 :按下 Ctrl-C 产生的信号仅会发送给前台进程。若在命令后添加 “&” 符号,可将命令对应的进程置于后台运行,此时 Shell 无需等待该后台进程完成,便可继续接收新的命令并启动其他进程。

  2. Shell 进程管理 :Shell 能够同时管理一个前台进程以及数量不限的后台进程,但唯有前台进程能够接收像 Ctrl-C 这类由控制键产生的信号。

  3. 信号接收特性 :前台进程在执行期间,用户可在任意时刻按下 Ctrl-C 产生信号,这意味着该进程的用户空间代码在执行的任何位置都有可能收到 SIGINT 信号进而被终止,所以信号对于进程的控制流程而言是异步的。

信号概念:信号是进程之间事件异步通知的一种方式,属于软中断。

三、深入信号世界

1. 信号身份证

kill -l //查看所有信号

        每个信号都有一个编号和一个宏定义名称,这些宏定义可以在signal.h中找到,其中1~31号信号是普通信号,34~64号信号是实时信号。

2. 信号记录原理

        当一个进程接收到某种信号后,该信号会被记录在该进程的进程控制块中。进程控制块本质上是一个结构体变量,对于信号而言,主要记录某种信号是否产生,可以用一个32位的位图来记录信号是否产生,比特位的位置代表信号编号,内容代表是否收到对应信号。

// 简化的PCB结构
struct task_struct {
    // ...
    unsigned long signal; // 32位位图
    // ...
};

示例位图:


3. 信号三处理法

        信号处理有三种可选动作:忽略此信号;执行信号的默认处理动作;提供一个信号处理函数,要求内核在处理信号时切换到用户态执行这个处理函数,即捕捉信号。

在Linux中,可通过man手册查看各个信号默认的处理动作,命令为 man 7 signal。 

处理方式生活比喻代码示例
默认按惯例拆快递signal(SIGINT, SIG_DFL)
忽略假装没听到敲门signal(SIGINT, SIG_IGN)
自定义定制特殊收件流程signal(SIGINT, handler)

http://www.kler.cn/a/591877.html

相关文章:

  • DeepSeek:AI 搜索引擎的革新者?
  • 【数据分享】1999—2023年地级市固定资产投资和对外经济贸易数据(Shp/Excel格式)
  • 浅谈鸿蒙跨平台开发框架ArkUI-X
  • 再学:call与delegatecall、call转账 Bank合约
  • dockerfile 编写入门
  • 2025年渗透测试面试题总结- 腾讯科恩实验室实习 二面(题目+回答)
  • 采购与供应链项目建议书(46页PPT)(文末有下载方式)
  • 从bootloader跳到APP需要几步?
  • C# Exe + Web 自动化 (BitComet 绿灯 自动化配置、设置)
  • 如何创建并保存HTML文件?零基础入门教程
  • 深入理解 Vue 的响应式原理:从 Vue 2 到 Vue 3
  • Tailwind CSS 学习笔记(一)
  • LeetCode 第11题~第13题
  • Express.js 是一个轻量级、灵活且功能强大的 Node.js Web 应用框架
  • 【保姆级教程】Windows系统+ollama+Docker+Anythingllm部署deepseek本地知识库问答大模型,可局域网多用户访问
  • 单片机开发资源分析的实战——以STM32G431RBT6为例子的单片机资源分析
  • Qt6.8实现麦克风音频输入音频采集保存wav文件
  • 代码随想录算法训练营第三十二天 | 509. 斐波那契数、70. 爬楼梯、746. 使用最小花费爬楼梯
  • 【第15届蓝桥杯】软件赛CB组省赛
  • 3 C#调用visionPro的toolblock的步骤