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

Linux信号集操作函数详解(掌握信号集,轻松管理进程信号)

Linux信号集操作函数详解(掌握信号集,轻松管理进程信号)

在Linux系统编程中,信号集是管理进程信号的核心概念。它允许程序员以位掩码的方式表示多个信号,从而高效地对信号进行阻塞、等待和处理。本文将详细讲解信号集操作函数的使用,包括初始化、添加、删除信号等基本操作,并深入介绍sigprocmasksigpending这两个关键函数,通过实例帮助小白快速上手。

Linux信号集操作函数详解(掌握信号集,轻松管理进程信号) 信号集 信号集操作函数 sigprocmask sigpending 第1张

一、什么是信号集?

信号集(signal set)是一种数据类型sigset_t,用于表示一组信号。在Linux内核中,每个进程都有三个重要的信号集:阻塞信号集(也被称为信号掩码)、未决信号集已决信号集。通过操作信号集,我们可以控制哪些信号被阻塞、哪些信号正在等待处理。

二、基础信号集操作函数

以下五个函数是操作信号集的基础,它们都作用于sigset_t类型的变量。使用时需包含头文件

  • sigemptyset:将信号集初始化为空,即不包含任何信号。
    int sigemptyset(sigset_t *set);
  • sigfillset:将信号集初始化为包含所有信号的集合。
    int sigfillset(sigset_t *set);
  • sigaddset:向信号集中添加一个指定的信号。
    int sigaddset(sigset_t *set, int signum);
  • sigdelset:从信号集中删除一个指定的信号。
    int sigdelset(sigset_t *set, int signum);
  • sigismember:测试一个指定的信号是否在信号集中。
    int sigismember(const sigset_t *set, int signum);

这些函数成功时返回0(sigismember返回1表示在集合中,0表示不在),出错返回-1并设置errno。

三、信号集的高级应用:sigprocmask 和 sigpending

掌握了基础操作后,我们需要了解如何将信号集应用于进程的信号控制。以下两个函数是核心:

  • sigprocmask:用于检查或修改进程的信号掩码(即阻塞信号集)。通过它,我们可以阻塞或解除阻塞特定信号,实现临界区保护。
    int sigprocmask(int how, const sigset_t *set, sigset_t *oldset);
    参数how决定如何修改:SIG_BLOCK(将set中的信号加入阻塞集)、SIG_UNBLOCK(从阻塞集中移除set中的信号)、SIG_SETMASK(直接用set替换当前阻塞集)。
  • sigpending:获取当前进程的未决信号集(即已经被发送但被阻塞的信号)。
    int sigpending(sigset_t *set);
    该函数将未决信号集存入set中,我们可以通过sigismember检查哪些信号处于未决状态。

四、实战示例:阻塞SIGINT并查看未决信号

下面通过一个完整的C程序演示sigprocmasksigpending的用法。程序先阻塞SIGINT(由Ctrl+C产生),然后发送SIGINT信号(通过raise函数模拟),接着检查未决信号集,最后解除阻塞。

    #include #include #include int main() {sigset_t newmask, oldmask, pendmask;// 1. 初始化信号集,添加SIGINTsigemptyset(&newmask);sigaddset(&newmask, SIGINT);// 2. 阻塞SIGINT,并保存旧掩码if (sigprocmask(SIG_BLOCK, &newmask, &oldmask) == -1) {perror("sigprocmask error");return 1;}printf("SIGINT blocked. Press Ctrl+C now - it won"t terminate the process.");sleep(5);  // 在这5秒内按Ctrl+C,信号会被阻塞// 3. 查看未决信号集if (sigpending(&pendmask) == -1) {perror("sigpending error");return 1;}if (sigismember(&pendmask, SIGINT)) {printf("SIGINT is pending (waiting to be delivered).");} else {printf("SIGINT is not pending.");}// 4. 解除阻塞,恢复旧掩码if (sigprocmask(SIG_SETMASK, &oldmask, NULL) == -1) {perror("sigprocmask restore error");return 1;}printf("SIGINT unblocked. If you pressed Ctrl+C earlier, it will be delivered now.");sleep(5);  // 如果之前有未决的SIGINT,此时进程会被终止return 0;}  

运行该程序,在第一次sleep期间按下Ctrl+C,可以看到未决信号集中包含SIGINT;解除阻塞后,进程立即收到SIGINT而终止。这个例子清晰地展示了信号集操作函数如何协同工作。

五、总结

本文从零开始介绍了Linux下的信号集及其相关操作函数,包括初始化、增删查改,以及高级控制函数sigprocmasksigpending。通过实例,读者可以直观理解信号阻塞与未决的机制。掌握这些函数,是编写健壮Linux程序的基础,也是深入理解进程间通信的重要一步。

—— 教程结束,希望对你有所帮助 ——