Linux 信号处理标志sa_flags详解
这些宏定义是 Linux 内核中用于 sigaction
结构体 sa_flags
字段的标志位,用于控制信号处理的行为。它们位于内核源码的 include/uapi/asm-generic/signal-defs.h
文件中。以下是每个标志的详细解释:
信号处理标志详解
-
SA_NOCLDSTOP
(0x00000001)- 含义:当子进程停止或恢复时,不产生
SIGCHLD
信号 - 用途:
默认情况下,当子进程停止(SIGSTOP
)或恢复(SIGCONT
)时,父进程会收到SIGCHLD
信号。设置此标志后,内核不会在这些情况下发送SIGCHLD
。
- 含义:当子进程停止或恢复时,不产生
-
SA_NOCLDWAIT
(0x00000002)- 含义:子进程退出时不创建僵尸进程
- 用途:
当设置此标志时,内核会在子进程终止时立即清理其资源,而不是使其成为僵尸进程。父进程调用wait()
将立即返回错误。
-
SA_SIGINFO
(0x00000004)- 含义:使用扩展信号处理函数
- 用途:
表示信号处理函数有三个参数:
其中void handler(int sig, siginfo_t *info, void *context)
siginfo_t
包含发送信号的进程PID、UID等详细信息。
-
SA_THIRTYTWO
(0x02000000)- 含义:恢复32位信号处理语义(历史遗留)
- 用途:
在64位系统上保持与旧32位信号处理的兼容性,现代代码通常不需要使用。
-
SA_RESTORER
(0x04000000)- 含义:使用信号恢复函数
- 用途:
表示sigaction
结构体中指定了sa_restorer
函数,用于信号处理完成后恢复上下文(主要用于兼容性)。
-
SA_ONSTACK
(0x08000000)- 含义:使用备选信号栈
- 用途:
当设置此标志时,信号处理函数将在sigaltstack()
设置的备选栈上执行,防止栈溢出导致信号无法处理。
-
SA_RESTART
(0x10000000)- 含义:被信号中断的系统调用自动重启
- 用途:
如果系统调用被信号中断,内核会自动重启该系统调用而不是返回EINTR
错误。
-
SA_NODEFER
(0x40000000)- 含义:不阻塞当前信号
- 用途:
默认情况下,当信号处理函数执行时,内核会自动阻塞相同信号。此标志允许信号处理函数被自身信号中断(可重入)。
-
SA_RESETHAND
(0x80000000)- 含义:信号处理完成后重置为默认操作
- 用途:
信号第一次触发时执行自定义处理函数,之后自动重置为默认行为(如SIG_DFL
)。
兼容性别名
#define SA_NOMASK SA_NODEFER // 同 SA_NODEFER
#define SA_ONESHOT SA_RESETHAND // 同 SA_RESETHAND
- 这些是为了保持与旧代码的兼容性而定义的别名
典型用法示例
#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;
}
内核实现位置
这些标志位在内核的信号处理流程中被使用,主要涉及:
- 信号发送:
kernel/signal.c
中的send_signal()
函数 - 信号处理:
arch/x86/kernel/signal.c
中的handle_signal()
函数 - 信号栈管理:
kernel/signal.c
中的get_sigframe()
函数
这些标志位通过 sigaction
系统调用从用户空间传递到内核空间,控制内核的信号处理行为,是Linux信号机制的核心组成部分。加粗样式