Linux进程信号详解(一):信号快速认识

一、信号快速认识

  • 信号(现实生活中):闹钟、红绿灯、上课铃声、狼烟、电话铃声、肚子叫、敲门声、脸色不好 ....

1.1 生活中的信号 ------ 快递的例子

想象你网购了很多商品:

  • 你能识别快递:你知道快递员打电话时该怎么处理。即使快递没有到来,你也知道快递来临的时候,你该如何处理快递 。 ------ 这是内置的识别能力

  • 信号产生前你就知道处理方法: 即使快递没到,你也知道"收到快递要拆开" ------ 进程在信号产生前就已经准备好了处理函数

  • **不必立即处理:**你正在打游戏,可以5分钟后下楼取快递 ------信号不要求立即处理,而是在"合适的时候"处理。

  • 记住有信号:你知道有一个快递到了但还没取 ------ 进程会保存未决信号

  • 处理方式有三种

    • 默认动作:开心拆快递

    • 自定义动作:(买了零食,分给同学一些)

    • 忽略:不理快递

基本结论

  • 识别信号是内核程序员内置的特性。

  • 信号产生前,进程已经知道如何处理。

  • 信号处理不是立即的,而是在合适的时候(从内核态返回用户态时)。

  • 信号到来 → 信号保存 → 信号处理。

  • 信号处理方式:忽略 ; 默认 ; 自定义【后续都叫信号捕捉】

快递到来的整个过程,对你来说,是异步的, 你不确定 , 快递员什么时候会给你打电话

1.2 键盘产生的信号

Makefile

复制代码
testSign:testSign.cc
	g++ -o $@ $^ -std=c++11
.PHONY:clean
clean:
	rm -f testSign

testSig.cc

复制代码
#include <iostream>
#include <unistd.h>

int main()
{
    int cnt = 0;
    while (true)
    {
        std::cout << "hello world," << cnt++ << std::endl;
        sleep(1);
    }

    return 0;
}

ctrl + c , 是给目标进程发送信号的 。 相当一部分的信号处理动作 , 就是让进程自己终止!

1.3 信号都有哪些?

kill -l :查看信号列表数字)大写的信号名

关键说明

  1. 每个信号都有编号宏定义名称 (如 2 号信号对应 SIGINT),宏定义在signal.h头文件中;
  2. 34 及以上为实时信号,用于实时进程通信,日常开发主要使用 34 以下的常规信号;
  3. 每个信号都有默认处理动作,可通过man 7 signal查看详细说明(如 SIGKILL 的默认动作是终止进程,且无法被捕捉和忽略)。

常用信号:

编号 名称 默认动作 含义
2 SIGINT 终止 终端中断(Ctrl+C)
3 SIGQUIT 终止+Core Dump 终端退出(Ctrl+\)
9 SIGKILL 终止 强制终止(不可捕捉、不可阻塞)
11 SIGSEGV 终止+Core Dump 段错误(非法内存访问)
14 SIGALRM 终止 闹钟信号
20 SIGTSTP 停止进程 终端停止(Ctrl+Z)

ctrl + c : 给目标进程发送 2)信号 !!!

收到信号,处理动作(捕捉):

1.4 证明:ctrl+c -> 二号信号

修改一下testSig.cc的代码

复制代码
#include <iostream>
#include <unistd.h>
#include <signal.h>

void handlerSig(int sig)
{
    std::cout << "获得了一个信号: " << sig << std::endl;
}

int main()
{
    signal(SIGINT,handlerSig);
    int cnt = 0;
    while (true)
    {
        std::cout << "hello world, " << cnt++ << std::endl;
        sleep(1);
    }

    return 0;
}

二、前台 & 后台进程?

2.1 现象查看

2.2 核心定义

特性 前台进程 (Foreground) 后台进程 (Background)
标准输入 ✅ 独占键盘输入 ❌ 无法从 stdin 读取
标准输出 ✅ 可以输出到终端 ✅ 可以输出到终端
键盘信号 ✅ 响应 Ctrl+C 等 ❌ 不响应键盘信号
数量限制 必须只有一个 可以有多个
创建方式 ./program ./program &
  • 前台进程唯一能接收键盘输入、获取标准输入的进程,同一时间 Shell 中只能有一个前台进程
  • 后台进程 :无法从键盘获取标准输入的进程,同一时间可以有多个后台进程
  • Shell 命令行进程本身:默认是前台进程,负责接收用户输入的命令。

2.3 为什么前台进程只能有一个?

键盘只有一个,输入数据一定是给一个确定的进程的!

这是硬件层面的限制------键盘是独占设备 。如果多个进程同时等待键盘输入,操作系统无法决定把按键发给谁。因此 Shell 设计了**作业控制(Job Control)**机制:

  • 前台作业:当前与终端交互的进程组

  • 后台作业:在后台运行,不占用终端输入

2.4 进程状态转换与作业控制命令

命令 作用 示例
jobs 查看所有后台任务 [1]+ Running ./test &
fg %n 将后台任务 n 提到前台 fg %1
bg %n 让暂停的后台任务继续运行 bg %1
Ctrl+Z 暂停当前前台进程,放入后台 进程变为 Stopped
Ctrl+C 向前台进程发送 SIGINT 信号 终止进程

2.5 关键场景:孤儿进程与后台化

复制代码
# 场景1:正常前台进程
$ ./testsig          # bash 子进程作为前台进程
# Ctrl+C 可以终止,因为键盘信号发给前台进程

# 场景2:后台运行
$ ./testsig &        # 立即放入后台
# Ctrl+C 杀不掉!因为键盘信号只发给前台进程

父进程先退出 → 孤儿进程自动后台化

复制代码
// 代码逻辑示意
int main() {
    if (fork() == 0) {
        // 子进程
        sleep(10);  // 模拟工作
    } else {
        // 父进程先退出
        exit(0);
    }
}

现象

  • 父进程(bash 的子进程)先退出

  • 子进程变成孤儿进程,被 init/systemd 收养

  • 自动提到后台(因为失去了控制终端的前台关联)

  • Ctrl+C 杀不掉 (已经是后台进程)

三、给进程发送信号的理解

发送信号的本质:修改目标进程的内核数据结构 (向目标进程写信号 = 修改位图)

信号是一种异步事件通知机制

  • 信号产生后,不是立即处理

  • 进程必须先把信号记录下来

  • 合适的时候(系统调用返回、中断返回)统一处理

为什么必须是操作系统来发送?

信号在内核中的存储:位图结构

复制代码
// include/linux/sched.h
struct task_struct {
    // ...
    unsigned long signal;      // 共享挂起信号(线程组共享)
    unsigned long blocked;     // 被阻塞的信号掩码
    struct sigpending pending; // 私有挂起信号队列
    // ...
};

位图解析

四、信号VS通信IPC

对比维度 信号(Signal) 通信 IPC(管道/消息队列/共享内存等)
本质 通知机制 数据传输机制
传递内容 只传递"发生了什么"(事件类型) 传递"具体的内容"(任意数据)
存储方式 用位图记录(1 bit) 用缓冲区存储(多字节)
数据承载 不能带数据(除 siginfo 外) 可以传输任意数据
同步方式 异步、立即记录 可能阻塞、支持同步/异步
控制权 操作系统强制干预 进程间协作完成
类比 门铃(有人来了) 快递(有具体物品)
相关推荐
mzhan0171 分钟前
Linux: config: CRYPTO_USER_API_AEAD
linux·安全·module
项目申报小狂人2 分钟前
一种使用双向长短时记忆网络结合鲸鱼优化算法的类火星矿物元素精确定量分析模型
人工智能·算法·lstm
wangjialelele7 分钟前
【SystemV】基于建造者模式的信号量
linux·c语言·c++·算法·建造者模式
源远流长jerry1 小时前
Linux 网络虚拟化深度解析:从 veth 设备对到容器网络实战
linux·运维·服务器·网络·性能优化·php
朔北之忘 Clancy1 小时前
2026 年 3 月青少年软编等考 C 语言一级真题解析
c语言·开发语言·c++·学习·青少年编程·题解·一级
Aaron15881 小时前
RFSOC+VU13P/VU9P+GPU多通道同步一体化解决方案
人工智能·嵌入式硬件·算法·matlab·fpga开发·硬件架构·基带工程
|_⊙1 小时前
Linux 深入理解文件(Ext2文件系统:上)
linux·运维·数据库
kidwjb1 小时前
Linux共享内存
linux·服务器·进程间通信
红茶要加冰1 小时前
七、正则表达式
linux·运维·正则表达式·shell
ALINX技术博客1 小时前
【黑金云课堂】FPGA技术教程Linux开发:串行通信接口与实时时钟模块
linux·fpga开发