Linux信号之标准信号与实时信号

Linux 信号

概述

Linux 系统支持多种信号, 用于进程间通信、进程控制和异常处理. 信号分为两类:

  • 标准信号 (1-31): POSIX 标准信号, 不排队, 可能丢失
  • 实时信号 (SIGRTMIN 到 SIGRTMAX, 通常 34-64): 可以排队, 不会丢失

标准信号 (1-31)

编号 信号名 默认动作 说明
1 SIGHUP Terminate 挂起信号. 当终端关闭或控制进程终止时发送. 常用于让守护进程重新读取配置文件
2 SIGINT Terminate 中断信号. 通常由 Ctrl+C 触发. 用于请求进程终止
3 SIGQUIT Core 退出信号. 通常由 Ctrl+\ 触发. 终止进程并生成 core dump
4 SIGILL Core 非法指令. 当进程尝试执行非法指令时由内核发送
5 SIGTRAP Core 跟踪陷阱. 由调试器使用, 用于断点
6 SIGABRT Core 中止信号. 由 abort() 函数发送, 用于异常终止
6 SIGIOT Core 与 SIGABRT 相同 (历史遗留)
7 SIGBUS Core 总线错误. 访问无效内存地址时发送 (对齐错误等)
8 SIGFPE Core 浮点异常. 算术运算错误 (除零、溢出等)
9 SIGKILL Terminate 强制终止. 不可捕获、不可阻塞、不可忽略. 用于强制杀死进程
10 SIGUSR1 Terminate 用户自定义信号 1. 应用程序可自由使用
11 SIGSEGV Core 段错误. 访问无效内存地址时发送
12 SIGUSR2 Terminate 用户自定义信号 2. 应用程序可自由使用
13 SIGPIPE Terminate 管道破裂. 向已关闭的管道写入时发送
14 SIGALRM Terminate 定时器信号. 由 alarm()setitimer(ITIMER_REAL, ...) 触发
15 SIGTERM Terminate 终止信号. 请求进程正常终止 (可捕获)
16 SIGSTKFLT Terminate 协处理器栈错误 (已废弃, 很少使用)
17 SIGCHLD Ignore 子进程状态改变. 子进程终止、停止或继续时发送给父进程
18 SIGCONT Ignore 继续信号. 恢复被停止的进程. 不可阻塞
19 SIGSTOP Stop 停止信号. 暂停进程执行. 不可捕获、不可阻塞、不可忽略
20 SIGTSTP Stop 终端停止信号. 通常由 Ctrl+Z 触发, 暂停进程
21 SIGTTIN Stop 后台进程尝试从终端读取时发送
22 SIGTTOU Stop 后台进程尝试向终端写入时发送
23 SIGURG Ignore 紧急数据. 套接字上有紧急数据到达时发送
24 SIGXCPU Core CPU 时间超限. 进程超过 CPU 时间限制时发送
25 SIGXFSZ Core 文件大小超限. 进程尝试创建超过文件大小限制的文件时发送
26 SIGVTALRM Terminate 虚拟定时器. 由 setitimer(ITIMER_VIRTUAL, ...) 触发
27 SIGPROF Terminate 性能分析定时器. 由 setitimer(ITIMER_PROF, ...) 触发
28 SIGWINCH Ignore 窗口大小改变. 终端窗口大小改变时发送
29 SIGIO Terminate I/O 就绪. 文件描述符可进行 I/O 操作时发送
29 SIGPOLL Terminate 与 SIGIO 相同 (System V 名称)
30 SIGPWR Terminate 电源故障. 系统电源故障时发送
31 SIGSYS Core 系统调用错误. 无效的系统调用时发送
31 SIGUNUSED Core 未使用信号 (与 SIGSYS 相同, 历史遗留)

默认动作说明

  • Terminate: 终止进程
  • Core: 终止进程并生成 core dump 文件
  • Stop: 暂停进程执行 (进入 TASK_STOPPED 状态)
  • Ignore: 忽略信号 (不执行任何操作)

特殊信号说明

不可捕获/阻塞的信号
  • SIGKILL (9): 强制终止, 不可捕获、不可阻塞、不可忽略
  • SIGSTOP (19): 强制停止, 不可捕获、不可阻塞、不可忽略
作业控制信号

以下信号用于作业控制 (shell 的前台/后台进程管理):

  • SIGSTOP (19): 停止进程
  • SIGTSTP (20): 终端停止 (可捕获)
  • SIGTTIN (21): 后台读终端
  • SIGTTOU (22): 后台写终端
  • SIGCONT (18): 继续被停止的进程

注意:

  • SIGCONT 会清除所有待处理的停止信号
  • 停止信号会清除待处理的 SIGCONT
  • SIGCONT 不可阻塞
用户自定义信号
  • SIGUSR1 (10): 用户自定义信号 1
  • SIGUSR2 (12): 用户自定义信号 2

这两个信号专门为应用程序保留, 默认行为是终止进程, 但可以被捕获和处理. 常用于进程间通信和自定义事件通知.

定时器信号
  • SIGALRM (14) : 实时定时器 (alarm(), setitimer(ITIMER_REAL, ...), timer_create())
  • SIGVTALRM (26) : 虚拟定时器 (setitimer(ITIMER_VIRTUAL, ...))
  • SIGPROF (27) : 性能分析定时器 (setitimer(ITIMER_PROF, ...))

实时信号 (SIGRTMIN 到 SIGRTMAX)

概述

实时信号是 POSIX.1b 扩展, 提供了比标准信号更强大的功能:

  • 编号范围 : SIGRTMIN (通常 34) 到 SIGRTMAX (通常 64)
  • 可以排队: 多个相同信号可以排队, 不会丢失
  • 传递数据 : 可以通过 sigqueue() 传递额外数据 (siginfo_t)
  • FIFO 顺序: 按先进先出顺序传递
  • 优先级: 实时信号优先于标准信号传递

实时信号编号

在大多数 Linux 系统上:

  • SIGRTMIN = 34
  • SIGRTMAX = 64
  • 共 31 个实时信号 (34-64)

注意 : 实时信号的编号可能因系统而异, 应使用 SIGRTMINSIGRTMAX 宏, 而不是硬编码数值.

实时信号特点

  1. 排队机制:

    • 标准信号不排队, 相同信号只保留一个
    • 实时信号可以排队, 多个相同信号都会传递
  2. 数据传递:

    c 复制代码
    union sigval {
        int sival_int;      // 整数值
        void *sival_ptr;     // 指针值
    };
  3. 使用方式:

    c 复制代码
    // 发送实时信号 (带数据)
    sigqueue(pid, SIGRTMIN, value);
    
    // 接收实时信号 (带数据)
    sigaction(sig, &sa, NULL);  // 使用 SA_SIGINFO 标志
  4. 应用场景:

    • 需要可靠传输的场景
    • 需要传递额外数据的场景
    • 需要多个相同信号排队的场景

信号分类总结

按用途分类

类别 信号 说明
终止信号 SIGTERM, SIGINT, SIGQUIT, SIGHUP 请求进程终止
强制终止 SIGKILL 强制杀死进程
异常信号 SIGSEGV, SIGBUS, SIGFPE, SIGILL, SIGABRT 程序异常
定时器信号 SIGALRM, SIGVTALRM, SIGPROF 定时器触发
作业控制 SIGSTOP, SIGTSTP, SIGCONT, SIGTTIN, SIGTTOU 进程控制
I/O 信号 SIGIO, SIGURG, SIGPIPE I/O 事件
资源限制 SIGXCPU, SIGXFSZ 资源超限
用户自定义 SIGUSR1, SIGUSR2 应用程序使用
实时信号 SIGRTMIN 到 SIGRTMAX 可排队信号

按默认动作分类

默认动作 信号数量 信号列表
Terminate 多数 SIGTERM, SIGINT, SIGHUP, SIGUSR1, SIGUSR2, SIGALRM, SIGPIPE, SIGKILL, SIGVTALRM, SIGPROF, SIGIO, SIGPWR, SIGRTMIN-SIGRTMAX
Core 8 SIGQUIT, SIGILL, SIGTRAP, SIGABRT, SIGBUS, SIGFPE, SIGSEGV, SIGXCPU, SIGXFSZ, SIGSYS
Stop 4 SIGSTOP, SIGTSTP, SIGTTIN, SIGTTOU
Ignore 3 SIGCHLD, SIGCONT, SIGURG, SIGWINCH

信号发送方式

命令行

bash 复制代码
# 发送信号给进程
kill -SIGTERM <pid>      # 发送 SIGTERM
kill -15 <pid>           # 发送信号 15 (SIGTERM)
kill -9 <pid>            # 发送 SIGKILL (强制终止)

# 查看所有信号
kill -l

系统调用

c 复制代码
// 发送标准信号
kill(pid, SIGTERM);

// 发送实时信号 (带数据)
sigqueue(pid, SIGRTMIN, value);

// 发送信号给进程组
killpg(pgrp, SIGTERM);

// 发送信号给自己
raise(SIGTERM);

注意事项

  1. 信号安全: 信号处理函数必须是信号安全的 (async-signal-safe)

    • 可以使用: write, _exit, alarm, signal
    • 避免使用: printf, malloc, free
  2. 信号丢失: 标准信号不排队, 可能丢失

    • 如果需要可靠传输, 使用实时信号
  3. 不可捕获信号 : SIGKILLSIGSTOP 不可捕获、阻塞或忽略

  4. 多线程: 在多线程程序中, 信号会发送到任意一个线程

    • 使用 pthread_sigmask() 在线程级别控制信号
  5. 实时信号编号 : 不要硬编码实时信号编号, 使用 SIGRTMINSIGRTMAX

相关文档

  • man 7 signal - 信号概述
  • man 2 kill - 发送信号
  • man 2 sigaction - 注册信号处理
  • man 2 sigqueue - 发送实时信号
  • man 2 sigprocmask - 阻塞信号

参考

  • POSIX.1-2001 标准
  • Linux 内核源码: include/asm-*/signal.h
  • Linux 内核源码: kernel/signal.c
相关推荐
QT 小鲜肉4 小时前
【Linux命令大全】001.文件管理之git命令(实操篇)
linux·服务器·笔记·git·elasticsearch
sishen41995 小时前
嵌入式Linux没有学习方向怎么办,嵌入式Linux怎么学
linux
逆风水手5 小时前
Ansible自动化运维入门指南
linux·运维·自动化·ansible
源代码•宸5 小时前
Leetcode—620. 有趣的电影&&Q3. 有趣的电影【简单】
数据库·后端·mysql·算法·leetcode·职场和发展
2301_800256116 小时前
地理空间数据库中的CPU 和 I/O 开销
数据库·算法·oracle
一个不知名程序员www6 小时前
算法学习入门---结构体和类(C++)
c++·算法
旖旎夜光6 小时前
Linux(3)(下)
linux·学习
小鹿学程序7 小时前
任务一-1.子任务一:基础环境准备
linux·bigdata