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

多线程与信号

Linux信号基础快速总结


1. 信号是什么?
  • 定义:轻量级进程间通信机制,用于通知进程特定事件发生(如用户输入、硬件异常、系统事件)。
  • 特点
    ✅ 异步传递(随时可能中断进程)
    ✅ 不可靠信号(标准信号不排队,可能丢失)
    ✅ 编号范围:131(标准信号),3264(实时信号)

2. 关键信号速查表
信号编号触发场景默认动作
SIGINT2Ctrl+C终止进程
SIGKILL9kill -9强制终止(不可捕获)
SIGTERM15默认终止命令(kill无参数)终止进程
SIGSTOP19Ctrl+Z暂停进程(不可捕获)
SIGSEGV11非法内存访问(段错误)终止+核心转储
SIGCHLD17子进程状态变化忽略
SIGALRM14定时器超时(alarm()终止进程

3. 信号处理三要素
  1. 默认行为

    • 终止进程(如SIGTERM
    • 暂停进程(如SIGSTOP
    • 生成核心转储(如SIGSEGV
  2. 忽略信号

    signal(SIGINT, SIG_IGN);  // 忽略Ctrl+C
    
  3. 自定义处理函数

    void handler(int sig) { /* 异步安全操作 */ }
    struct sigaction sa = {.sa_handler = handler,.sa_flags = SA_RESTART  // 自动重启被中断的系统调用
    };
    sigaction(SIGINT, &sa, NULL);
    

4. 信号发送方式
  • 命令行工具
    kill -SIGTERM 1234     # 向PID 1234发送SIGTERM
    killall -9 app_name    # 强制终止所有名为app_name的进程
    
  • 编程接口
    kill(pid, SIGUSR1);    // 向指定进程发送信号
    raise(SIGALRM);        // 向当前进程发送信号(等同于kill(getpid(), sig))
    

5. 必须掌握的要点
  • 不可捕获的信号
    SIGKILL(9)和SIGSTOP(19)无法被捕获、阻塞或忽略,用于强制控制进程。

  • 异步安全函数
    信号处理函数中只能调用异步安全函数(如write()_exit()),禁止使用printf()malloc()等。

  • 信号阻塞

    sigset_t set;
    sigemptyset(&set);
    sigaddset(&set, SIGINT);
    sigprocmask(SIG_BLOCK, &set, NULL); // 阻塞SIGINT
    
  • 实时信号(RT Signal)

    • 支持排队(不丢失多次发送)
    • 可携带额外数据(通过sigqueue()发送)

6. 多线程与信号
  • 信号屏蔽:每个线程独立设置信号屏蔽字
    pthread_sigmask(SIG_BLOCK, &set, NULL); // 当前线程屏蔽信号
    
  • 信号处理:所有线程共享同一信号处理函数。
  • 定向发送
    pthread_kill(thread_id, SIGUSR1); // 向指定线程发送信号
    

7. 核心实践原则
  1. 精简处理函数:仅设置标志位,避免复杂逻辑。

    volatile sig_atomic_t flag = 0;  // 原子类型确保线程安全
    void handler(int sig) { flag = 1; }
    
  2. 处理被中断的系统调用

    while ((n = read(fd, buf, size)) < 0 && errno == EINTR); // 重启read()
    
  3. 避免信号竞争:关键代码段阻塞信号。

  4. 核心转储调试

    ulimit -c unlimited          # 启用核心转储
    gcc -g prog.c && ./a.out     # 编译带调试信息
    gdb ./a.out core             # 分析崩溃原因
    

8. 常见问题
  • Q: 为什么SIGKILL无法被捕获?
    A: 内核强制处理,防止进程拒绝终止。

  • Q: 多次发送SIGINT会丢失吗?
    A: 是的,标准信号不排队,多次发送可能合并为一次。

  • Q: 如何优雅终止子进程?
    A: 父进程捕获SIGCHLD,调用waitpid()回收资源。


9. 总结思维导图
Linux信号
├── 生命周期:生成 → 递送 → 处理
├── 关键操作
│   ├── 发送(kill/raise/sigqueue)
│   ├── 处理(默认/忽略/自定义)
│   └── 阻塞(sigprocmask)
├── 多线程
│   ├── 线程独立屏蔽信号
│   └── 全局处理函数
└── 安全原则├── 异步安全函数└── 原子标志传递

掌握这些核心知识,即可应对90%的信号相关开发与调试场景! 🚀

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

相关文章:

  • 软件设计师-错题笔记-软件工程基础知识
  • 总结C/C++中程序内存区域划分
  • 判断公网IP办法
  • Java SolonMCP 实现 MCP 实践全解析:SSE 与 STDIO 通信模式详解
  • Kubernetes排错(十三):Pod间偶发超时问题排查
  • 期刊 | 《电讯技术》
  • [SAP] SAP ERP用户参数设置
  • Funplus 服务端开发实习 面经
  • 分享一些资料供大家学习
  • PCB 设计 | 1A / 10A / 100A
  • 41、IIS 应⽤程序池集成模式和经典模式的区别?
  • 点和体素哪个好
  • 损失函数的选择和技术分析:深度学习模型训练的指南
  • GO语言-导入自定义包
  • 嵌入式STM32学习——振动传感器控制继电器开关灯
  • 力扣-二叉树-101 对称二叉树
  • fast-livo2原理
  • 【Java学习笔记】属性重写问题
  • 全栈项目实战:Vue3+Node.js开发博客系统
  • Python-MCPAgent开发-DeepSeek版本
  • MySQL索引原理以及SQL优化(二)
  • 【更新至2023年】1999-2023年上市公司人工智能词频统计数据(年报词频统计)
  • RGA模块讲解
  • 低代码平台与 AI 融合:从 Activity 流程到智能 ITSM 的落地实践
  • 单片机-STM32部分:12、I2C
  • 2003-2022年 地级市-政府干预程度指标数据-社科数据
  • springboot3整合SpringSecurity实现登录校验与权限认证
  • c++ 类的语法2
  • Windows使用虚拟环境执行sh脚本
  • 【深度学习】将本地工程上传到Colab运行的方法