当前位置:首页 > 系统教程 > 正文

Linux sigaction函数详解(信号处理的强大工具)

Linux sigaction函数详解(信号处理的强大工具)

Linux信号处理 中,信号是一种异步事件,用于通知进程某个条件发生了。sigaction 函数是Linux系统提供的一个强大且灵活的接口,用于设置信号处理器。相比于传统的 signal 函数,sigaction 提供了更精细的控制和可移植性,是现代Linux信号处理的首选工具。

1. sigaction 函数原型

    #include int sigaction(int signum, const struct sigaction *act, struct sigaction *oldact);  

signum 指定要捕获的信号(如 SIGINTSIGTERM),act 是新的信号处理方式,oldact 用于保存之前的处理方式。成功返回0,失败返回-1。

2. struct sigaction 结构体详解

    struct sigaction {    void     (*sa_handler)(int);      // 简单信号处理器    void     (*sa_sigaction)(int, siginfo_t *, void ); // 带附加信息的处理器    sigset_t   sa_mask;                // 信号掩码    int        sa_flags;                // 标志位    void     (sa_restorer)(void);     // 已废弃,不使用};  
  • sa_handler:传统的信号处理函数,只接收信号编号。
  • sa_sigaction:当 sa_flags 包含 SA_SIGINFO 时使用,可获取发送信号的详细信息(如发送者PID、用户ID等)。
  • sa_mask:指定在信号处理器执行期间需要阻塞的信号集(即 信号掩码)。这可以防止某些信号中断处理器。
  • sa_flags:控制信号处理的行为,常用值包括 SA_RESTART(自动重启被中断的系统调用)、SA_RESETHAND(处理器执行后恢复默认行为)、SA_NODEFER(不自动阻塞当前信号)等。

3. 基础示例:捕获 SIGINT

    #include #include #include void handler(int sig) {    printf("捕获到信号 %d", sig);}int main() {    struct sigaction sa;    sa.sa_handler = handler;    sigemptyset(&sa.sa_mask);    sa.sa_flags = 0; // 无特殊标志    if (sigaction(SIGINT, &sa, NULL) == -1) {        perror("sigaction");        return 1;    }    while(1) {        printf("等待信号...");        sleep(1);    }    return 0;}  

按下 Ctrl+C 会触发 handler,打印信息。注意我们使用了 sigaction函数 而非 signal,确保了可移植性和行为一致性。

Linux sigaction函数详解(信号处理的强大工具) Linux信号处理 sigaction函数 信号处理器 信号掩码 第1张

4. 进阶示例:使用 siginfo_t 获取发送者信息

    #include #include #include void handler(int sig, siginfo_t *info, void *context) {    printf("信号 %d 来自进程 %d", sig, info->si_pid);}int main() {    struct sigaction sa;    sa.sa_sigaction = handler;    sigemptyset(&sa.sa_mask);    sa.sa_flags = SA_SIGINFO; // 使用 siginfo_t    sigaction(SIGUSR1, &sa, NULL);    while(1) pause();    return 0;}  

通过 SA_SIGINFO 标志,信号处理器 可以接收 siginfo_t 结构,其中包含信号的详细信息,如发送者的PID、用户ID、信号产生的原因等。

5. 信号掩码与阻塞

sa_mask 定义了在执行处理器期间需要阻塞的信号集。例如,如果在处理 SIGINT 时希望阻塞 SIGQUIT,可以设置 sa_mask 包含 SIGQUIT。系统会自动将当前信号加入掩码(除非设置了 SA_NODEFER),防止嵌套中断。

6. 注意事项与最佳实践

  • 在信号处理器中只调用异步信号安全的函数(如 writesigaction 本身)。
  • 使用 sigaction 而非 signal,因为不同平台 signal 行为差异大。
  • 合理设置 sa_flags,如 SA_RESTART 可减少需要处理 EINTR 的情况。
  • 在多线程程序中,信号处理更加复杂,建议使用专用信号处理线程。

7. 总结

sigaction函数 是Linux系统进行 Linux信号处理 的核心接口,通过它你可以精细控制信号的行为、获取更多上下文信息,并管理 信号掩码。掌握 sigaction 是编写健壮信号处理程序的基础。