在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())、硬件异常(如段错误)、软件条件(如定时器到期)。无论来源如何,最终都会由内核递送给目标进程。
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()。
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。希望本文能帮助你从入门到精通!
本文由主机测评网于2026-02-14发表在主机测评网_免费VPS_免费云服务器_免费独立服务器,如有疑问,请联系我们。
本文链接:https://vpshk.cn/20260225179.html