Linux 信号处理标志sa_flags详解

这些宏定义是 Linux 内核中用于 sigaction 结构体 sa_flags 字段的标志位,用于控制信号处理的行为。它们位于内核源码的 include/uapi/asm-generic/signal-defs.h 文件中。以下是每个标志的详细解释:

信号处理标志详解

  1. SA_NOCLDSTOP (0x00000001)

    • 含义 :当子进程停止或恢复时,不产生 SIGCHLD 信号
    • 用途
      默认情况下,当子进程停止(SIGSTOP)或恢复(SIGCONT)时,父进程会收到 SIGCHLD 信号。设置此标志后,内核不会在这些情况下发送 SIGCHLD
  2. SA_NOCLDWAIT (0x00000002)

    • 含义:子进程退出时不创建僵尸进程
    • 用途
      当设置此标志时,内核会在子进程终止时立即清理其资源,而不是使其成为僵尸进程。父进程调用 wait() 将立即返回错误。
  3. SA_SIGINFO (0x00000004)

    • 含义:使用扩展信号处理函数

    • 用途
      表示信号处理函数有三个参数:

      c 复制代码
      void handler(int sig, siginfo_t *info, void *context)

      其中 siginfo_t 包含发送信号的进程PID、UID等详细信息。

  4. SA_THIRTYTWO (0x02000000)

    • 含义:恢复32位信号处理语义(历史遗留)
    • 用途
      在64位系统上保持与旧32位信号处理的兼容性,现代代码通常不需要使用。
  5. SA_RESTORER (0x04000000)

    • 含义:使用信号恢复函数
    • 用途
      表示 sigaction 结构体中指定了 sa_restorer 函数,用于信号处理完成后恢复上下文(主要用于兼容性)。
  6. SA_ONSTACK (0x08000000)

    • 含义:使用备选信号栈
    • 用途
      当设置此标志时,信号处理函数将在 sigaltstack() 设置的备选栈上执行,防止栈溢出导致信号无法处理。
  7. SA_RESTART (0x10000000)

    • 含义:被信号中断的系统调用自动重启
    • 用途
      如果系统调用被信号中断,内核会自动重启该系统调用而不是返回 EINTR 错误。
  8. SA_NODEFER (0x40000000)

    • 含义:不阻塞当前信号
    • 用途
      默认情况下,当信号处理函数执行时,内核会自动阻塞相同信号。此标志允许信号处理函数被自身信号中断(可重入)。
  9. SA_RESETHAND (0x80000000)

    • 含义:信号处理完成后重置为默认操作
    • 用途
      信号第一次触发时执行自定义处理函数,之后自动重置为默认行为(如 SIG_DFL)。

兼容性别名

c 复制代码
#define SA_NOMASK    SA_NODEFER   // 同 SA_NODEFER
#define SA_ONESHOT   SA_RESETHAND // 同 SA_RESETHAND
  • 这些是为了保持与旧代码的兼容性而定义的别名

典型用法示例

c 复制代码
#include <signal.h>

void signal_handler(int sig) {
    // 信号处理逻辑
}

int main() {
    struct sigaction sa;
    
    sa.sa_handler = signal_handler;
    sigemptyset(&sa.sa_mask);  // 初始化信号掩码
    
    // 设置标志:自动重启 + 使用备选栈 + 不阻塞自身信号
    sa.sa_flags = SA_RESTART | SA_ONSTACK | SA_NODEFER;
    
    sigaction(SIGINT, &sa, NULL);  // 注册SIGINT处理
    
    // ...程序主循环...
    return 0;
}

内核实现位置

这些标志位在内核的信号处理流程中被使用,主要涉及:

  1. 信号发送kernel/signal.c 中的 send_signal() 函数
  2. 信号处理arch/x86/kernel/signal.c 中的 handle_signal() 函数
  3. 信号栈管理kernel/signal.c 中的 get_sigframe() 函数

这些标志位通过 sigaction 系统调用从用户空间传递到内核空间,控制内核的信号处理行为,是Linux信号机制的核心组成部分。

相关推荐
霖.2411 分钟前
K8s实践中的重点知识
linux·云原生·kubernetes
truesnow15 分钟前
速通 awk:一篇文章带你理解 awk 原理,大量实战案例让你马上成为 awk 专家
linux
Lyre丶44 分钟前
Ubuntu 24.04 LTS 安装GAMIT
linux·经验分享·学习·ubuntu·gamit
namekong81 小时前
ubuntu 通过下面几种方式查看系统 重启时间/开机时间:
linux·运维·ubuntu
爱奥尼欧1 小时前
【Linux】网络部分——网络基础(协议与网络传输)
linux·网络·arm开发
_dindong1 小时前
Linux系统编程:线程概念
linux·运维·笔记·学习
雪饼android之路2 小时前
【Android】 android suspend/resume总结(3)
android·linux
老黄编程3 小时前
ubuntu如何查看一个内核模块被什么模块依赖(内核模块信息常用命令)?
linux·运维·ubuntu
知北游天3 小时前
Linux网络:使用UDP实现网络通信(服务端&&客户端)
linux·网络·udp
半桔3 小时前
【网络编程】TCP 粘包处理:手动序列化反序列化与报头封装的完整方案
linux·网络·c++·网络协议·tcp/ip