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

Linux信号处理详解 从基本概念到高级应用

Linux信号处理详解 从基本概念到高级应用

Linux信号处理详解 从基本概念到高级应用 Linux信号处理 信号处理函数 sigaction 信号阻塞 第1张

在Linux系统编程中,Linux信号处理是一个至关重要的主题。信号是一种异步通知机制,用于通知进程某个事件已经发生。无论是初学者还是资深开发者,理解信号的工作方式都是写出健壮程序的基础。本文将带你从零开始,逐步深入到高级应用,确保即使小白也能轻松掌握。

一、什么是信号?

信号是Linux/Unix系统中进程间通信的一种简单形式,它本质上是一个软件中断。当进程接收到一个信号时,它会暂停当前执行,转而处理该信号(除非信号被阻塞或忽略)。例如,按下 Ctrl+C 会向前台进程发送 SIGINT 信号,默认终止进程。

二、常见信号列表

  • SIGINT (2) — 终端中断,通常由 Ctrl+C 触发
  • SIGTERM (15) — 终止信号,可被捕获或忽略
  • SIGKILL (9) — 强制终止,不可被捕获或忽略
  • SIGUSR1 (10)SIGUSR2 (12) — 用户自定义信号
  • SIGCHLD (17) — 子进程状态改变时发送给父进程

三、信号的产生方式

信号可以通过多种方式产生:键盘组合键(如Ctrl+C)、系统调用(如 kill()raise())、硬件异常(如段错误)、软件条件(如定时器到期)。无论来源如何,最终都会由内核递送给目标进程。

四、信号处理的基本方法

1. 使用signal函数

signal() 是最早期的信号处理函数,它允许为特定信号指定处理方式:忽略、默认或自定义处理函数。

#include #include #include void handler(int sig) {    printf("捕获到信号 %d", sig);}int main() {    signal(SIGINT, handler);  // 自定义处理SIGINT    while(1) {        sleep(1);    }    return 0;}

注意:signal() 在不同Unix版本间行为略有差异,现代开发更推荐使用 sigaction()

2. 使用sigaction函数(推荐)

sigaction 提供了更强大和可移植的信号接口。它可以精细控制信号处理标志、获取旧处理方式等。

#include #include #include void handler(int sig) {    printf("sigaction 捕获信号 %d", sig);}int main() {    struct sigaction sa;    sa.sa_handler = handler;    sigemptyset(&sa.sa_mask);    sa.sa_flags = 0;    sigaction(SIGINT, &sa, NULL);    while(1) pause();    return 0;}

sigaction 允许在信号处理期间阻塞其他信号(通过sa_mask),是实现可靠信号处理的关键。

五、信号集与信号阻塞

信号阻塞是指暂时阻止信号递送,但信号仍然 pending。Linux 提供了信号集操作函数:sigemptyset()sigfillset()sigaddset() 等。配合 sigprocmask() 可以设置进程的信号屏蔽字。

sigset_t set;sigemptyset(&set);sigaddset(&set, SIGINT);sigprocmask(SIG_BLOCK, &set, NULL);  // 阻塞SIGINT

通过 sigpending() 可以获取当前 pending 的信号。这在实现临界区保护时非常有用。

六、多线程中的信号处理

在多线程程序中,信号的行为更为复杂。每个线程都有自己的信号屏蔽字,但信号递送只会选择一个线程处理(通常是未阻塞该信号的线程)。推荐在多线程中使用 pthread_sigmask() 控制线程信号屏蔽,并指定专门的线程处理所有信号。

七、总结与注意事项

Linux信号处理是系统编程的基石。掌握基本概念、信号处理函数sigaction信号阻塞,能让你写出更健壮的代码。需要注意:信号处理函数中只能调用异步安全函数(如write,不可调用printf);避免在信号处理函数中持有锁;尽量使用sigaction而非signal。希望本文能帮助你从入门到精通!