【Linux】进程信号

【Linux】进程信号

在 Linux 编程世界中,信号(Signal)机制是一种极为关键的异步通信方式。它不仅是进程间通信的基础之一,也是操作系统与进程互动的重要通道。本文将从生活中的类比引入,再逐步深入技术细节,帮助读者系统性地掌握信号的概念、产生、处理、阻塞机制及相关编程实践。


一、信号是什么?

1.1 从生活场景谈起

你网购了几件商品,快递员在楼下时通知你取件,但你可能正忙着打游戏,五分钟后才下去。这段"知道快递来了但还没取"的时间,就像进程接收到信号但尚未处理的"未决状态"。

取快递的方式也多样:

  • 默认处理:自己打开快递使用;
  • 自定义处理:送人;
  • 忽略处理:扔床头不理。

这种过程是异步的,快递(信号)何时到来无法预知,只能在收到通知后"在合适的时机"处理。

1.2 从技术场景看信号

举例说明,当我们在 Shell 中执行一个前台程序时按下 Ctrl+C

  • 键盘产生一个中断;
  • 操作系统捕捉中断并发送 SIGINT 信号;
  • 前台进程收到信号并终止。

二、信号基础知识

2.1 信号的定义

信号是进程间用于事件通知的一种机制,本质上属于"软中断",用于通知目标进程发生了某个事件。

2.2 信号种类与查看方式

使用命令 kill -l 可以查看系统支持的所有信号。信号通常由宏定义标识(如 SIGINT 是信号编号 2),可在 signal.h 中查到。


三、信号的产生方式

3.1 终端按键产生

如:

  • Ctrl+CSIGINT,默认终止进程;
  • Ctrl+\SIGQUIT,默认终止并生成 core dump。

3.2 调用系统函数发送

常用函数:

  • kill(pid, signo):向指定进程发送信号;
  • raise(signo):向当前进程自身发送信号;
  • abort():强制终止自身进程;
  • alarm(seconds):定时发出 SIGALRM

3.3 软件条件触发

如:

  • 写入已关闭的管道 → SIGPIPE
  • 调用 alarm() → 在指定秒数后触发 SIGALRM

3.4 硬件异常触发

如:

  • 除零 → SIGFPE
  • 访问非法地址 → SIGSEGV

四、信号的处理方式

信号的处理动作有三种:

  1. 忽略;
  2. 执行默认动作;
  3. 自定义处理函数(捕捉)。

示例代码:

c 复制代码
signal(SIGINT, handler); // 捕捉SIGINT

4.1 Core Dump 简介

当进程异常终止时,将内存内容保存为文件 core,可用于调试分析。需使用 ulimit -c 命令允许生成 core 文件。


五、信号的捕捉机制

5.1 内核中的捕捉流程

信号捕捉的本质是注册一个回调函数,在信号递达时中断当前流程并调用该函数。处理完信号后,再恢复原有上下文继续执行。

5.2 使用 sigaction

sigaction 提供更安全和灵活的信号处理方式,支持设置额外屏蔽信号、恢复上下文等操作。

示例用法:

c 复制代码
struct sigaction act;
act.sa_handler = handler;
sigaction(SIGINT, &act, NULL);

六、信号的阻塞与未决

6.1 概念区分

  • 阻塞(Block):信号被暂时挂起,不立即处理;
  • 未决(Pending):信号已产生,但因被阻塞暂未递达;
  • 递达(Delivery):信号处理动作被实际执行。

6.2 内核实现方式

信号在 PCB 中用两个标志位表示:

  • 是否阻塞;
  • 是否未决。

如果信号被阻塞,系统仅设置其未决标志;待解阻塞后再处理。


七、信号集与相关函数

信号集类型 sigset_t 用于描述多个信号状态。

常用函数包括:

c 复制代码
sigemptyset(&set);   // 初始化为空
sigfillset(&set);    // 所有信号
sigaddset(&set, sig);
sigdelset(&set, sig);
sigismember(&set, sig); // 是否包含某信号

7.1 操作信号屏蔽字:sigprocmask

用于读取/更改当前进程的阻塞信号集。

c 复制代码
sigprocmask(SIG_BLOCK, &set, NULL);

7.2 查询未决信号:sigpending

c 复制代码
sigpending(&pending_set);

八、可重入函数与信号安全

在信号处理函数中使用的代码必须是可重入 的。不可重入函数(如 malloc, printf)在信号处理时会引发数据错乱。


九、关键字 volatile 的作用

当变量被 volatile 修饰时,编译器不会优化其访问操作,确保对该变量的访问都在真实内存中进行,防止因缓存导致的判断失效。

c 复制代码
volatile int flag = 0;

避免如下问题:

c 复制代码
while (!flag); // 如果没有volatile修饰,可能永远不退出循环

十、SIGCHLD 信号与子进程管理

SIGCHLD 信号在子进程终止时发送给父进程。

10.1 信号处理函数方式

使用 signal(SIGCHLD, handler) 捕捉信号,在处理函数中调用 waitpid 回收子进程资源,避免僵尸进程。

10.2 SIG_IGN 简化处理

SIGCHLD 的处理动作设为 SIG_IGN 可自动回收子进程(Linux 专属行为)。


结语:

信号机制的设计体现了操作系统对异步事件控制的精巧思路。通过信号,进程得以与系统高效交互,也为开发者提供了强大的编程工具。

相关推荐
树℡独5 小时前
ns-3仿真之应用层(五)
服务器·网络·tcp/ip·ns3
小小管写大大码5 小时前
如何让vscode变得更智能?vscode接入claude实现自动编程
运维·ide·vscode·自动化·编辑器·ai编程·腾讯云ai代码助手
嵩山小老虎5 小时前
Windows 10/11 安装 WSL2 并配置 VSCode 开发环境(C 语言 / Linux API 适用)
linux·windows·vscode
Fleshy数模6 小时前
CentOS7 安装配置 MySQL5.7 完整教程(本地虚拟机学习版)
linux·mysql·centos
zhang133830890756 小时前
CG-09H 超声波风速风向传感器 加热型 ABS材质 重量轻 没有机械部件
大数据·运维·网络·人工智能·自动化
a41324476 小时前
ubuntu 25 安装vllm
linux·服务器·ubuntu·vllm
Fᴏʀ ʏ꯭ᴏ꯭ᴜ꯭.7 小时前
Keepalived VIP迁移邮件告警配置指南
运维·服务器·笔记
物联网软硬件开发-轨物科技7 小时前
【轨物洞见】告别“被动维修”!预测性运维如何重塑老旧电站的资产价值?
运维·人工智能
程序员允诺7 小时前
[DevOps实战] 彻底解决依赖地狱:如何编译全静态、可移植的 Xorriso 工具
运维·devops
酣大智7 小时前
接口模式参数
运维·网络·网络协议·tcp/ip