在上一篇文章中,我们介绍了Linux信号的基本概念和常用函数。本文作为信号(下),将深入探讨信号集操作、信号阻塞、高级信号处理函数sigaction以及可重入函数等主题,帮助读者全面掌握Linux信号处理的核心技术。
信号集(signal set)用于表示多个信号的集合,类型为sigset_t。Linux提供了一组函数来操作信号集,这些是进行信号集操作的基础。
sigemptyset(sigset_t *set):清空信号集sigfillset(sigset_t *set):将所有信号加入集合sigaddset(sigset_t *set, int signo):添加指定信号sigdelset(sigset_t *set, int signo):删除指定信号sigismember(const sigset_t *set, int signo):测试信号是否存在使用这些函数前,必须用sigemptyset或sigfillset初始化信号集。
每个进程都有一个信号掩码(blocked signal set),用于指定当前阻塞哪些信号。当一个信号被阻塞时,它不会递送给进程,而是保持在未决状态(pending)。进程可以使用sigprocmask来修改信号掩码,使用sigpending获取当前未决信号集。
sigset_t newmask, oldmask, pendmask;sigemptyset(&newmask);sigaddset(&newmask, SIGINT);sigprocmask(SIG_BLOCK, &newmask, &oldmask); // 阻塞SIGINT// 临界区代码sigpending(&pendmask); // 获取未决信号集if (sigismember(&pendmask, SIGINT)) printf("SIGINT is pending");sigprocmask(SIG_SETMASK, &oldmask, NULL); // 恢复原掩码signal函数在不同Unix实现中行为差异较大,推荐使用POSIX的sigaction函数,它提供了更强大和可移植的信号处理机制。sigaction可以指定信号处理函数、设置信号掩码、以及控制信号行为。这是学习sigaction函数的关键。
struct sigaction newact, oldact;newact.sa_handler = handler; // 处理函数sigemptyset(&newact.sa_mask); // 执行处理函数期间阻塞的信号集newact.sa_flags = 0; // 标志位sigaction(SIGINT, &newact, &oldact);sa_flags可包含SA_RESTART(使被信号中断的系统调用自动重启)、SA_SIGINFO(使用带附加信息的处理函数)等。

在信号处理函数中,只能调用异步信号安全的函数(async-signal-safe functions)。例如printf不是安全的,因为它使用了全局缓冲区,可能被中断导致数据混乱。这就是可重入函数的概念——函数在被多次调用时仍然能正确工作。常见的安全函数有write、_exit、sigaction等。编写信号处理函数时应避免调用不安全函数,或者只设置标志变量(需声明为volatile sig_atomic_t)。
Linux支持实时信号(范围SIGRTMIN到SIGRTMAX),它们具有排队能力、支持携带数据(通过sigqueue发送),且保证递送顺序。实时信号弥补了标准信号可能丢失的不足。
本文详细介绍了Linux信号处理的进阶内容,包括信号集操作、信号阻塞、sigaction函数的使用以及可重入函数的重要性。掌握这些知识,可以编写更健壮和可移植的信号处理程序。希望读者通过实践加深对Linux信号处理的理解。
本文由主机测评网于2026-02-26发表在主机测评网_免费VPS_免费云服务器_免费独立服务器,如有疑问,请联系我们。
本文链接:https://www.vpshk.cn/20260227409.html