Linux 信号控制

目录

一、背景:为什么要研究信号屏蔽与未决信号?

二、代码拆解:从示例看核心逻辑

[1. 信号集的初始化与屏蔽设置](#1. 信号集的初始化与屏蔽设置)

[2. 未决信号的查询与打印](#2. 未决信号的查询与打印)

三、关键问题解答:穿透代码看本质

[问题 1:"我可以将所有的信号都进行屏蔽,信号不就不会被处理了吗?"](#问题 1:“我可以将所有的信号都进行屏蔽,信号不就不会被处理了吗?”)

[问题 2:"sigset_t 是在哪里开辟的空间?"](#问题 2:“sigset_t 是在哪里开辟的空间?”)

[问题 3:"未决信号的本质是什么?"](#问题 3:“未决信号的本质是什么?”)

四、扩展:信号屏蔽与未决的典型应用场景

[场景 1:关键逻辑的 "原子性" 保障](#场景 1:关键逻辑的 “原子性” 保障)

[场景 2:批量处理未决信号](#场景 2:批量处理未决信号)

五、总结


在 Linux 系统编程中,信号是进程间通信和系统事件通知的重要机制。今天我们就以一段关于 ** 信号屏蔽(sigprocmask)未决信号(sigpending)** 的代码为切入点,深入剖析这两个概念的底层逻辑与实际应用。

一、背景:为什么要研究信号屏蔽与未决信号?

在多任务、多事件的系统环境中,进程可能会同时收到多个信号。但有些场景下,我们希望暂时屏蔽某些信号 (比如在执行关键逻辑时,不希望被干扰);同时,我们也需要知道有哪些信号被屏蔽后处于 "待处理" 状态 (即未决信号)。这两个机制 ------sigprocmasksigpending,就是用来解决这些问题的关键工具。

二、代码拆解:从示例看核心逻辑

先看我们的示例代码,它主要做了两件事:屏蔽所有 1-31 号信号 ,并循环打印当前的未决信号集合

1. 信号集的初始化与屏蔽设置

运行

cpp 复制代码
sigset_t bset, oset;
sigemptyset(&bset);
sigemptyset(&oset);
for (int i = 1; i <= 31; i++)
{
    sigaddset(&bset, i); // 将1-31号信号加入屏蔽集
}
sigprocmask(SIG_SETMASK, &bset, &oset);
  • sigset_t:是 Linux 中用于表示信号集合的数据结构,本质上是一个位图(每一位对应一个信号)。
  • sigemptyset:初始化一个空的信号集合(所有位设为 0)。
  • sigaddset:将指定信号加入集合(对应位设为 1)。
  • sigprocmask核心系统调用 ,用于修改进程的信号屏蔽字 (即进程当前屏蔽哪些信号)。SIG_SETMASK表示用bset完全替换当前的屏蔽字,oset用于保存旧的屏蔽字(以便后续恢复)。

2. 未决信号的查询与打印

运行

cpp 复制代码
sigset_t pending;
while (true)
{
    int n = sigpending(&pending); // 获取当前进程的未决信号集合
    if (n < 0)
        continue;
    PrintPending(pending); // 打印未决信号的位图
    sleep(1);
}

void PrintPending(sigset_t &pending)
{
    for (int signo = 31; signo >= 1; signo--)
    {
        if (sigismember(&pending, signo)) // 判断信号是否在未决集合中
            cout << "1";
        else
            cout << "0";
    }
    cout << "\n\n";
}
  • sigpending:获取进程的未决信号集合(即被屏蔽且已经发送到进程,但尚未被处理的信号)。
  • sigismember:判断某个信号是否在信号集合中。
  • 打印逻辑:从 31 号到 1 号信号依次判断,输出 "1" 表示该信号未决,"0" 表示未未决,这样就能直观看到未决信号的位图状态。

三、关键问题解答:穿透代码看本质

问题 1:"我可以将所有的信号都进行屏蔽,信号不就不会被处理了吗?"

回答:大部分信号会被屏蔽,但有例外!

在 Linux 中,9号信号(SIGKILL)19号信号(SIGSTOP)不可屏蔽 的。这是系统级的安全设计 ------ 比如SIGKILL用于强制终止进程,若能被屏蔽,进程就可能无法被杀死,导致系统资源泄漏;SIGSTOP用于暂停进程,同理需要保证其强制性。

所以,即使代码中尝试屏蔽所有 1-31 号信号,SIGKILLSIGSTOP仍然可以突破屏蔽,作用于进程。

问题 2:"sigset_t 是在哪里开辟的空间?"

回答:在用户栈上,属于进程的用户空间。

sigset_t bset, oset;是在main函数中定义的局部变量,因此存储在进程的用户栈 中(属于用户空间内存)。当调用sigprocmask时,内核会读取用户空间中bset的值,进而修改内核中进程task_struct里的信号屏蔽字。

问题 3:"未决信号的本质是什么?"

回答:未决信号是 "被屏蔽且已送达" 的信号的临时存储。

每个进程的task_struct中,有一个未决信号集合 (pending)和一个信号屏蔽字(mask)。当一个信号被发送到进程时:

  • 若该信号未被屏蔽(mask 中对应位为 0),则进程会立即处理(执行默认动作或自定义处理器);
  • 若该信号被屏蔽 (mask 中对应位为 1),则会被记录到未决集合(pending 中对应位置 1),直到屏蔽被解除,才会被处理。

四、扩展:信号屏蔽与未决的典型应用场景

场景 1:关键逻辑的 "原子性" 保障

在执行一段不希望被信号打断的关键逻辑时(比如数据库事务、文件写入的关键步骤),可以先屏蔽信号,执行完逻辑后再解除屏蔽:

运行

cpp 复制代码
sigset_t oldmask, newmask;
sigemptyset(&newmask);
sigaddset(&newmask, SIGINT); // 屏蔽Ctrl+C信号(2号)

sigprocmask(SIG_BLOCK, &newmask, &oldmask); // 保存旧屏蔽字,屏蔽SIGINT

// 执行关键逻辑...

sigprocmask(SIG_SETMASK, &oldmask, NULL); // 恢复旧屏蔽字,解除SIGINT屏蔽

场景 2:批量处理未决信号

有时我们希望 "积攒" 一批信号,然后一次性处理。可以先屏蔽信号,等业务逻辑完成后,查询未决信号并逐个处理:

运行

cpp 复制代码
// 屏蔽信号
sigset_t mask, oldmask;
sigfillset(&mask); // 填充所有信号(除不可屏蔽的)
sigprocmask(SIG_SETMASK, &mask, &oldmask);

// 执行业务逻辑,期间收到的信号会进入未决状态...

// 查询并处理未决信号
sigset_t pending;
sigpending(&pending);
for (int signo = 1; signo <= 31; signo++)
{
    if (sigismember(&pending, signo))
    {
        cout << "处理未决信号:" << signo << endl;
        // 这里可以调用信号处理函数
    }
}

// 恢复屏蔽字
sigprocmask(SIG_SETMASK, &oldmask, NULL);

五、总结

通过这段代码和对原理的剖析,我们可以清晰地理解:

  • sigprocmask是进程 "主动控制哪些信号可以打扰自己" 的工具;
  • sigpending是进程 "查看有哪些被屏蔽的信号在排队等待处理" 的窗口;
  • 信号屏蔽与未决机制,是 Linux 系统中进程对信号 "精细管控" 的核心手段,在系统编程、服务器开发等场景中有着广泛应用。

希望这篇博客能帮大家穿透代码,真正理解信号屏蔽与未决的底层逻辑~

相关推荐
努力努力再努力wz3 小时前
【Linux进阶系列】:信号(下)
java·linux·运维·服务器·开发语言·数据结构·c++
☆璇4 小时前
【Linux】传输层协议UDP
linux·运维·udp
孤廖4 小时前
面试官问 Linux 编译调试?gcc 编译流程 + gdb 断点调试 + git 版本控制,连 Makefile 都标好了
linux·服务器·c++·人工智能·git·算法·github
终焉代码4 小时前
【Linux】进程初阶(1)——基本进程理解
linux·运维·服务器·c++·学习·1024程序员节
我想吃余4 小时前
Linux进程间通信:管道与System V IPC的全解析
linux·服务器·c++
egoist20234 小时前
[linux仓库]打开线程的“房产证”:地址空间规划与分页式管理详解[线程·壹]
linux·页表·地址空间·分页式存储管理·缺页异常
Dreamboat-L5 小时前
从零开始在云服务器上部署Gitlab
运维·服务器·gitlab
喵了meme5 小时前
Linux学习日记6:文件IO与标准IO
linux·c语言·学习
wanhengidc8 小时前
云手机在网络游戏中的主要功能
运维·服务器·游戏·智能手机