在Linux系统中,进程信号是进程间通信的一种异步通知机制,用于通知进程发生了某个事件。信号本质上是软件层次上对中断机制的模拟,它可以在任何时间发送给进程,进程需要做出相应的处理。本文作为信号系列的第一篇,将深入探讨信号产生的多种方式以及信号保存在内核中的实现原理。
Linux系统定义了标准信号(如SIGINT、SIGKILL等),每个信号都有一个唯一的编号和默认动作。信号的生命周期包括:产生、保存(未决)、递送和处理。本文重点讲解前两个阶段,即信号产生与信号保存。
信号的产生可以来自多种场景,主要分为以下几类:
这些产生方式最终都会转化为内核向目标进程的PCB中写入一个信号记录,即进入信号保存阶段。
每个进程的PCB(task_struct)中维护了三个与信号相关的位图:pending(未决信号集)、block(阻塞信号集)和handler(信号处理函数表)。信号产生后,内核会将对应信号的比特位置1,表示该信号已经产生但尚未被处理(即未决状态)。信号的保存就是通过pending位图实现的。
阻塞信号集(block)用于屏蔽某些信号,被屏蔽的信号即使产生也不会被递送,仍然停留在pending中,直到解除屏蔽。这种机制为信号处理提供了灵活的控制能力。
用户空间可以通过一系列函数操作信号集:
sigemptyset()、sigfillset()、sigaddset()等用于操作信号集。sigprocmask()用于读取或更改进程的阻塞信号集。sigpending()用于获取当前未决信号集。下面是一个简单示例,演示如何屏蔽SIGINT信号并查看未决状态:
#include #include #include int main() { sigset_t newmask, oldmask, pendmask; sigemptyset(&newmask); sigaddset(&newmask, SIGINT); // 将SIGINT加入屏蔽集 sigprocmask(SIG_BLOCK, &newmask, &oldmask); // 阻塞SIGINT printf("SIGINT blocked, press Ctrl+C in 5 seconds..."); sleep(5); sigpending(&pendmask); // 获取未决信号集 if (sigismember(&pendmask, SIGINT)) printf("SIGINT is pending"); // 如果期间按了Ctrl+C,则pending中SIGINT位为1 sigprocmask(SIG_SETMASK, &oldmask, NULL); // 解除阻塞 printf("SIGINT unblocked, exiting"); return 0;} 运行该程序,在5秒内按下Ctrl+C,可以看到pending信号被捕获,但进程并未终止,因为信号被阻塞保存了。当解除阻塞后,信号才会递送(默认动作终止进程)。
本文详细介绍了进程信号的产生来源(硬件、软件、终端、系统调用)以及信号在内核中的保存机制(pending和block位图)。理解信号的产生与保存是深入学习信号处理(如自定义信号处理函数)的基础。下一篇文章我们将继续探讨信号的递送与处理过程。
本文由主机测评网于2026-03-12发表在主机测评网_免费VPS_免费云服务器_免费独立服务器,如有疑问,请联系我们。
本文链接:https://vpshk.cn/20260330699.html