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

Linux信号处理详解

Linux信号处理详解

从基本概念到高级应用

信号是Linux/Unix系统中进程间通信的一种异步通知机制,用于通知进程发生了特定事件。本文将详细介绍信号处理的基本概念、常用API以及高级应用,帮助读者全面掌握Linux信号编程。

Linux信号处理详解 信号处理 信号掩码 信号处理器 sigaction 第1张

1. 信号基本概念

信号本质上是软中断,每种信号都有一个唯一的编号和名称(如SIGINT、SIGTERM)。信号可以由用户(按Ctrl+C)、硬件异常(如段错误)、其他进程通过kill系统调用产生。

2. 常见信号列表

  • SIGINT (2): 终端中断,通常由Ctrl+C触发,默认终止进程。
  • SIGQUIT (3): 终端退出,Ctrl+\触发,默认终止并生成core文件。
  • SIGKILL (9): 强制终止,不可捕获或忽略。
  • SIGTERM (15): 软件终止信号,可捕获,用于优雅退出。
  • SIGALRM (14): 定时器超时。
  • 等等...

3. 信号处理方式

进程可以选择三种方式处理信号:默认处理、忽略、或者自定义信号处理器(signal handler)。

3.1 使用signal()函数

#include void (signal(int signum, void (handler)(int)))(int);// 示例:捕获SIGINTvoid handle_sigint(int sig) {    write(1, "Caught SIGINT\n", 15);}int main() {    signal(SIGINT, handle_sigint);    // ...}

3.2 使用sigaction()函数(推荐)

sigaction提供了更强大的功能,如信号掩码设置、信号传递额外信息等,且可移植性更好。

#include int sigaction(int signum, const struct sigaction act, struct sigaction oldact);struct sigaction {    void     (sa_handler)(int);    void     (sa_sigaction)(int, siginfo_t *, void );    sigset_t   sa_mask;    int        sa_flags;    void     (sa_restorer)(void);};

示例:

struct sigaction sa;sa.sa_handler = handle_sigint;sigemptyset(&sa.sa_mask);sa.sa_flags = 0;sigaction(SIGINT, &sa, NULL);

4. 信号掩码与阻塞

每个进程都有一个信号掩码(signal mask),用于阻塞某些信号。被阻塞的信号不会递送给进程,但会保持在未决状态(pending)。

#include int sigprocmask(int how, const sigset_t *set, sigset_t *oldset);// how: SIG_BLOCK, SIG_UNBLOCK, SIG_SETMASK

示例:阻塞SIGINT

sigset_t block_set;sigemptyset(&block_set);sigaddset(&block_set, SIGINT);sigprocmask(SIG_BLOCK, &block_set, NULL);

5. 高级应用

5.1 实时信号

实时信号(信号编号从SIGRTMIN到SIGRTMAX)支持排队和附加数据,可通过sigqueue()发送。

union sigval value;value.sival_int = 123;sigqueue(target_pid, SIGRTMIN, value);

5.2 多线程中的信号

每个线程有自己的信号掩码,但信号处理函数是进程共享的。使用pthread_sigmask()管理线程信号掩码。

5.3 信号与I/O多路复用

Linux提供signalfd,允许将信号转换为文件描述符,便于与select/epoll协同使用。

6. 注意事项与最佳实践

  • 信号处理器中只能调用异步信号安全函数(如write,但不能调用printf)。
  • 避免在信号处理器中操作全局数据结构,防止竞态。
  • 常用技巧:在信号处理器中只设置一个全局标志,在主循环中检查。
  • 使用sigaction代替signal以获得确定的行为。

7. 总结

本文从信号处理的基础讲起,涵盖了信号掩码、信号处理器、sigaction等核心概念,并介绍了实时信号和多线程环境下的信号处理。掌握这些知识,可以帮助开发者编写健壮的Linux应用程序。