在Linux系统中,Linux信号机制是一种进程间通信的异步方式,用于通知进程某个事件已经发生。它类似于软件中断,可以打断进程的正常执行流程,转而执行信号处理函数。信号机制让操作系统能够对进程进行控制和管理,例如用户按下Ctrl+C时发送SIGINT信号终止进程。
信号可以通过多种方式产生:键盘输入(如Ctrl+C产生SIGINT)、硬件异常(如段错误产生SIGSEGV)、软件条件(如alarm定时器到期产生SIGALRM)、以及使用kill命令或系统调用(kill()、raise())显式发送。常见的信号包括:
SIGINT (2): 中断信号,通常由Ctrl+C产生。SIGTERM (15): 终止信号,kill命令默认发送。SIGKILL (9): 强制终止,不能被捕获或忽略。SIGSEGV (11): 段错误,非法内存访问。进程可以决定暂时阻塞某些信号,使其不会立即递达,但信号仍然处于挂起(pending)状态。这是通过信号阻塞机制实现的。每个进程维护两个位向量:阻塞信号集(block set)和未决信号集(pending set)。当信号被阻塞时,它不会递达,直到解除阻塞。
操作阻塞信号集的关键函数:
sigset_t newset, oldset;sigemptyset(&newset);sigaddset(&newset, SIGINT);sigprocmask(SIG_BLOCK, &newset, &oldset); // 阻塞SIGINTsigpending(&pending); // 获取当前未决信号 通过sigprocmask可以动态修改进程的阻塞信号集,而sigpending可以查看当前有哪些信号被阻塞但尚未处理。
信号的处理方式有三种:默认处理(SIG_DFL)、忽略处理(SIG_IGN)和自定义处理函数。传统的signal()函数可以安装信号处理函数,但它的行为在不同UNIX变体间有差异,推荐使用sigaction函数,它提供更清晰的控制和可移植性。
struct sigaction act, oldact;act.sa_handler = my_handler; // 自定义函数sigemptyset(&act.sa_mask); // 在处理函数执行期间阻塞的信号集act.sa_flags = 0;sigaction(SIGINT, &act, &oldact); sigaction函数允许我们指定在处理信号期间额外阻塞的信号集,以及设置标志(如SA_RESTART自动重启被中断的系统调用)。它是实现可靠信号处理的首选。
当信号递达时,进程正在执行用户态代码,然后被中断进入内核态。内核处理完信号后,在返回用户态之前检查是否有信号需要处理。如果有,并且进程注册了自定义处理函数,内核会修改用户栈,使得从内核返回后直接执行信号处理函数,处理完毕后再通过特殊的返回方式(如sigreturn)恢复原来的执行上下文。整个过程对用户程序是透明的。
#include #include #include void handler(int sig) { printf("捕获到信号 %d", sig);}int main() { sigset_t newset, oldset, pend; struct sigaction act; // 设置SIGINT处理函数 act.sa_handler = handler; sigemptyset(&act.sa_mask); act.sa_flags = 0; sigaction(SIGINT, &act, NULL); // 阻塞SIGINT sigemptyset(&newset); sigaddset(&newset, SIGINT); sigprocmask(SIG_BLOCK, &newset, &oldset); printf("SIGINT被阻塞,请在5秒内尝试按Ctrl+C"); sleep(5); // 检查未决信号 sigpending(&pend); if (sigismember(&pend, SIGINT)) printf("有挂起的SIGINT信号"); // 解除阻塞,信号会被递达,执行handler sigprocmask(SIG_SETMASK, &oldset, NULL); printf("SIGINT已解除阻塞,信号将立即处理"); sleep(2); return 0;} 这个示例演示了如何阻塞SIGINT,然后检查其挂起状态,最后解除阻塞使其被处理。
在信号处理函数中,只能调用异步信号安全的函数(即可重入函数),例如write(),而不能调用printf()、malloc()等。另外,要避免使用signal(),因为它可能在处理期间重置处理函数为默认行为,推荐使用sigaction函数。理解Linux信号机制和进程信号处理的细节对于编写健壮的应用程序至关重要。
本文深入解析了Linux信号机制,从信号的产生、保存(阻塞)到处理,重点介绍了信号阻塞和sigaction函数的使用。掌握这些技巧可以帮助开发者更好地控制进程行为,避免竞态条件和不可预期的中断。希望这篇教程对您有所帮助!
本文由主机测评网于2026-02-26发表在主机测评网_免费VPS_免费云服务器_免费独立服务器,如有疑问,请联系我们。
本文链接:https://www.vpshk.cn/20260227395.html