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

sigaction结构体详解

sigaction 结构体详解

sigaction 是 Unix/Linux 系统编程中用于管理信号处理行为的核心数据结构。它通过 sigaction() 系统调用设置信号处理方式,比传统的 signal() 函数更灵活、安全。


结构体定义(POSIX 标准)
#include <signal.h>struct sigaction {void     (*sa_handler)(int);         // 基础信号处理函数void     (*sa_sigaction)(int, siginfo_t *, void *); // 高级信号处理函数sigset_t   sa_mask;                  // 执行处理函数期间阻塞的信号集int        sa_flags;                 // 控制标志位void     (*sa_restorer)(void);       // 已废弃,勿用
};

成员详解
  1. sa_handler

    • 类型: void (*)(int)
    • 作用: 指向传统信号处理函数(接受信号编号 int 作为参数)。
    • 特殊值:
      • SIG_IGN: 忽略信号
      • SIG_DFL: 恢复默认行为
  2. sa_sigaction

    • 类型: void (*)(int, siginfo_t *, void *)
    • 作用: 高级信号处理函数(需设置 SA_SIGINFO 标志)。
    • 参数:
      • int signo: 信号编号
      • siginfo_t *info: 携带额外信号信息(来源进程、错误码等)
      • void *context: 进程上下文(寄存器状态等)
  3. sa_mask

    • 类型: sigset_t(信号集)
    • 作用: 在执行信号处理函数期间,阻塞指定的信号集(防止嵌套中断)。
    • 注意:
      • 当前处理的信号自动被阻塞(除非设置 SA_NODEFER)。
      • 使用 sigemptyset()sigaddset() 等操作信号集。
  4. sa_flags

    • 关键标志位(通过位掩码 | 组合):
      标志作用
      SA_SIGINFO使用 sa_sigaction(而非 sa_handler)获取详细信息
      SA_RESTART被信号中断的系统调用自动重启
      SA_NODEFER执行处理函数时不自动阻塞当前信号(允许递归处理)
      SA_RESETHAND处理完成后将信号恢复为默认行为(类似传统 signal() 的一次性特性)
      SA_ONSTACK使用备选信号栈(通过 sigaltstack 设置)
  5. sa_restorer

    • 已废弃,现代系统无需使用。

关键机制说明
  1. 信号阻塞规则

    • 当信号处理函数执行时:
      • 当前信号自动加入阻塞集(除非 SA_NODEFER)。
      • sa_mask 中指定的信号被阻塞。
    • 处理完成后,阻塞集恢复为调用前的状态。
  2. sa_handler vs sa_sigaction

    • 两者共享同一存储空间,只能选其一。
    • sa_flags 包含 SA_SIGINFO,则使用 sa_sigaction;否则使用 sa_handler
  3. siginfo_t 结构示例

    typedef struct {int      si_signo;     // 信号编号int      si_code;      // 信号来源(如 USER/KILL/SEGV)pid_t    si_pid;       // 发送信号的进程IDuid_t    si_uid;       // 发送者的真实用户IDvoid    *si_addr;      // 引发故障的内存地址(如 SIGSEGV)int      si_status;    // 退出状态(SIGCHLD 时有效)// ... 其他扩展字段
    } siginfo_t;
    

使用示例
1. 基础用法(sa_handler
#include <signal.h>
#include <stdio.h>
#include <unistd.h>void handler(int sig) {printf("Received SIGINT!\n");
}int main() {struct sigaction sa;sa.sa_handler = handler;   // 设置处理函数sigemptyset(&sa.sa_mask);  // 清空调用时阻塞的信号集sa.sa_flags = 0;           // 无特殊标志sigaction(SIGINT, &sa, NULL); // 注册 SIGINTwhile(1) pause();          // 等待信号return 0;
}
2. 高级用法(sa_sigaction
#include <signal.h>
#include <stdio.h>void advanced_handler(int sig, siginfo_t *info, void *ucontext) {printf("Signal %d from PID: %d, UID: %d\n", sig, info->si_pid, info->si_uid);
}int main() {struct sigaction sa;sa.sa_sigaction = advanced_handler;sigemptyset(&sa.sa_mask);sa.sa_flags = SA_SIGINFO;  // 启用高级处理sigaction(SIGINT, &sa, NULL);while(1) pause();return 0;
}

最佳实践
  1. 优先选择 sigaction 而非 signal

    • sigaction 行为明确,可跨平台移植(signal() 在不同系统实现不一致)。
  2. 始终初始化 sa_mask

    • 使用 sigemptyset()sigfillset() 显式设置阻塞集,避免未定义行为。
  3. 需要额外信息时用 SA_SIGINFO

    • 例如获取信号发送者的 PID、内存错误地址等。
  4. 考虑 SA_RESTART

    • 对需要自动重启的系统调用(如 read()write())更友好。
  5. 避免使用 SA_RESETHAND

    • 可能导致信号处理重置为默认行为,引发意外结果(如程序退出)。
http://www.dtcms.com/a/318229.html

相关文章:

  • 推荐一款优质的开源博客与内容管理系统
  • 集团敏捷组织转型项目研讨材料(105页PPT)精品
  • Mac安装WebStorm for Mac v2025.1.1
  • PDF注释的加载和保存的实现
  • Enhancing Long Video Question Answering with Scene-Localized Frame Grouping
  • python中的推导式
  • Android PDFBox 的使用指南
  • 力扣热题100------136.只出现一次的数字
  • 【纵火犯的春天】纵火犯是如何解题leetcode的?
  • Python驱动的无人机多光谱-点云融合技术在生态三维建模与碳储量/生物量/LULC估算中的全流程实战
  • JDK9+ Method.class.getDeclaredFields() Method实例将不能再直接通过反射修改
  • 无人机航拍数据集|第4期 无人机太阳光伏板红外目标检测YOLO数据集10945张yolov11/yolov8/yolov5可训练
  • 大疆无人机使用eport连接Jetson主板实现目标检测
  • selenium操作指南
  • 前端路由守卫
  • JavaWeb服务器/servlet容器(Tomcat、Undertow 、WebLogic)
  • 前端应用场景题目(待总结优化)
  • 攻防世界WEB(新手模式)20-unseping
  • 基于 kubeadm 搭建 k8s 集群
  • 京东商品评论接口开发全指南:从数据获取到分析应用实战
  • 【20205CVPR-目标检测方向】基于事件的高效目标检测:具有空间和时间注意力的混合神经网络
  • Lodash 的终极进化Radashi
  • JAVA 程序员cursor 和idea 结合编程
  • 北京JAVA基础面试30天打卡03
  • SAP MR51 显示不是ALV格式的问题
  • 开源远程工具rustdesk
  • 力扣 hot100 Day67
  • Linux firewall 防火墙管理
  • SpringBoot 接入SSE实现消息实时推送的优点,原理以及实现
  • React:生命周期