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

Linux信号保存与处理机制详解

Linux信号的保存与处理涉及多个关键机制,以下是详细的总结:

1. 信号的保存

  • 进程描述符(task_struct):每个进程的PCB中包含信号相关信息。
    • pending信号集:记录已到达但未处理的信号(未决信号)。每个信号对应一个位,置1表示信号待处理。
    • blocked信号屏蔽字:标识被阻塞(屏蔽)的信号。被屏蔽的信号将暂不递送,直到解除屏蔽。
  • 实时信号队列:实时信号(SIGRTMIN~SIGRTMAX)支持排队,内核为每个进程维护多个队列,确保多次发送的同一信号被依次处理。

2. 信号的处理方式

  • 默认动作:如终止进程(SIGTERM)、忽略(SIGCHLD)或生成核心转储(SIGSEGV)。
  • 忽略信号:通过SIG_IGN显式忽略,但SIGKILL和SIGSTOP不可忽略。
  • 自定义处理函数:用户注册的信号处理函数(通过signal()sigaction()),需注意函数需为异步信号安全。

3. 信号处理流程

  1. 信号产生:通过硬件(如除零)、终端(Ctrl+C)、kill()系统调用等方式触发。
  2. 记录到pending:内核将信号标记在目标进程的pending集合中。
  3. 递送检查:在进程从内核态返回用户态时(如系统调用结束、中断处理完成),检查未被屏蔽的pending信号。
  4. 执行处理函数
    • 内核临时切换到用户态执行处理函数。
    • 处理函数返回后,通过sigreturn系统调用恢复原上下文。
    • 默认情况下,正在处理的信号会被自动阻塞,防止重入。

4. 关键系统调用与函数

  • sigprocmask:修改进程的信号屏蔽字,控制哪些信号被阻塞。
  • sigaction:设置信号处理方式,支持设置SA_RESTART(自动重启被中断的系统调用)及SA_SIGINFO(携带额外信息)。
  • sigpending:获取当前未决的信号集。
  • kill/raise:向进程或自身发送信号。
  • alarm:设置定时器发送SIGALRM。

5. 实时信号 vs 非实时信号

  • 非实时信号(标准信号):如SIGINT、SIGTERM,不支持排队,多次发送可能丢失。
  • 实时信号:通过sigqueue()发送并附带数据,支持可靠排队,确保多次信号被依次处理。

6. 多线程中的信号处理

  • 线程拥有独立的信号屏蔽字,但信号处理函数为进程内共享。
  • 信号可定向到特定线程(如通过pthread_kill()),未处理的信号由主线程处理。

7. 注意事项

  • 可重入性:处理函数应使用异步信号安全函数(如write()),避免调用printf()malloc()等非安全函数。
  • 原子性:通过sig_atomic_t类型变量在信号处理函数与主程序间安全传递状态。
  • 竞态条件:正确处理信号屏蔽与临界区保护,防止条件竞争。

示例场景

#include <signal.h>
#include <stdio.h>
#include <unistd.h>void handler(int sig) {write(STDOUT_FILENO, "Received SIGINT!\n", 17);
}int main() {struct sigaction sa;sa.sa_handler = handler;sigemptyset(&sa.sa_mask);sa.sa_flags = SA_RESTART;sigaction(SIGINT, &sa, NULL);while(1) {pause(); // 等待信号}return 0;
}

此代码注册SIGINT的处理函数,按下Ctrl+C时打印消息,处理期间自动阻塞SIGINT,避免递归调用。

总结

理解Linux信号的保存与处理机制,需掌握信号的生命周期(产生、保存、递送)、处理函数的设计约束(可重入性、安全性),以及多线程环境下的复杂性。合理使用信号能提升程序的健壮性,但需谨慎处理异步事件带来的挑战。

http://www.xdnf.cn/news/948385.html

相关文章:

  • 自然语言处理——循环神经网络
  • PKIX path building failed问题小结
  • Element-Plus:popconfirm与tooltip一起使用不生效?
  • Spring数据访问模块设计
  • Python自然语言处理库之gensim使用详解
  • Appuploader:在WindowsLinux上完成iOS APP上架的一种解决方案
  • RLHF vs RLVR:对齐学习中的两种强化方式详解
  • Rsync+inotify+nfs实现数据实时备份方案
  • Socket 编程
  • 架构设计之存储高性能——非关系型数据库(NoSQL)
  • 代购商城系统怎么选?从业务痛点看系统核心价值
  • SOC-ESP32S3部分:QA-关于唤醒词更改及配置操作步骤
  • 解锁Vscode:C/C++环境配置超详细指南
  • Python训练营---DAY49
  • 卷积神经网络设计指南:从理论到实践的经验总结
  • FDMA:解锁PL DDR性能的“高速快递系统”
  • Java 与 MySQL 性能优化:MySQL 慢 SQL 诊断与分析方法详解
  • 论文笔记:Urban Computing in the Era of Large Language Models
  • 多模态大语言模型arxiv论文略读(113)
  • Vue3+ts项目,在ts文件中导入vue文件,报错:找不到模块“./App.vue“或响应的类型声明
  • Easy Rules规则引擎:轻量级Java规则处理实践指南
  • 微机原理与接口技术,期末冲刺复习资料(四)
  • Python_day49cbam模块介绍
  • 华为云Flexus+DeepSeek征文 | 基于Dify构建具备联网搜索能力的知识库问答助手
  • 从线上名片到商业引擎:企业如何用官网重构市场竞争力?
  • 从数据报表到决策大脑:AI重构电商决策链条
  • 客户案例 | 短视频点播企业海外视频加速与成本优化:MediaPackage+Cloudfront 技术重构实践
  • 篇章十 数据结构——排序
  • 用HTML5+CSS3+JavaScript实现找不同游戏
  • c语言tips-结构体数组 VS 链表宏:`list_for_each_entry` 的优势与局限对比分析