当前位置: 首页 > news >正文

进程的信号掩码,信号集,sigprocmask函数

目录

核心逻辑

信号集

进程的信号掩码

sigprocmask系统调用

函数原型

参数解释

返回值

示例代码

sigpending系统调用

示例代码

被挂起的信号

进程掩码与sigaction


核心逻辑

        正常情况下,进程收到信号后,会执行信号默认的处理动作,例如终止进程。但是有些时候进程在执行一些代码的时候,不希望在这个时候收到信号而终止。于是就需要在执行这部分代码前先阻塞某些信号,执行后解除阻塞。这就是本篇要讲解的事。基本流程如下:

  1. 在执行这部分代码前,把要阻塞的信号放在信号集中
  2. 用sigprocmask函数将信号集中的信号阻塞
  3. 执行这部分不希望接收某些信号的代码
  4. 解除阻塞

信号集

        Linux用数据结构sigset_t表示一组信号集,下列是对信号集的各种操作方法:(后文实操后,大家一目了然)

  • int sigemptyset(sigset_t *set);清空一个信号集,即把信号集中所有信号都设置为未包含状态。成功时返回 0,失败时返回 -1。
  • int sigfillset(sigset_t *set);将信号集中所有信号都设置为包含状态,即填充信号集。成功时返回 0,失败时返回 -1。
  • int sigaddset(sigset_t *set, int signum);将指定的信号 signum 添加到信号集 set 中。成功时返回 0,失败时返回 -1。
  • int sigdelset(sigset_t *set, int signum);从信号集 set 中移除指定的信号 signum。成功时返回 0,失败时返回 -1。
  • int sigismember(const sigset_t *set, int signum);检查指定的信号 signum 是否在信号集 set 中。如果信号 signum 在信号集 set 中,返回 1;如果不在,返回 0;如果出错(如无效的信号集指针),返回 -1。

进程的信号掩码

        进程想要阻塞某些信号,把这些信号都放在一个数据结构sigset_t下的对象,即信号集中。这个信号集就可以被看做进程的信号掩码。

sigprocmask系统调用

        sigprocmask用于设置或查看进程的信号掩码

函数原型

int sigprocmask(int how, const sigset_t *set, sigset_t *oldset);

参数解释

  • how:指定如何修改信号掩码,常见取值有:
    • SIG_BLOCK:将 set 中的信号添加到当前信号掩码中,即新的信号掩码是当前信号掩码和 set 的并集。
    • SIG_UNBLOCK:从当前信号掩码中移除 set 中的信号,新的信号掩码是当前信号掩码和 set 的差集。
    • SIG_SETMASK:将当前信号掩码设置为 set,即覆盖当前信号掩码。
  • set:指向一个信号集,该信号集指定了要进行添加、移除或设置的信号。如果 how 为 SIG_BLOCK 或 SIG_UNBLOCKset 中信号会按相应规则修改当前信号掩码;如果 how 为 SIG_SETMASKset 直接成为新的信号掩码。若 set 为 NULL,则 how 的值会被忽略,此时 sigprocmask 仅用于获取当前信号掩码。
  • oldset:指向一个信号集,用于保存旧的信号掩码。如果不需要保存旧的信号掩码,可以将其设置为 NULL

返回值

        成功时返回 0,失败时返回 -1,并设置 errno 以指示错误原因。

示例代码

#include <stdio.h>
#include <signal.h>
#include <unistd.h>int main() {sigset_t new_mask, old_mask;sigemptyset(&new_mask);sigaddset(&new_mask, SIGINT);// 阻塞SIGINT信号if (sigprocmask(SIG_BLOCK, &new_mask, &old_mask) == -1) {perror("sigprocmask");return 1;}printf("SIGINT is blocked. Press Ctrl + C to test...\n");sleep(5);// 恢复旧的信号掩码if (sigprocmask(SIG_SETMASK, &old_mask, NULL) == -1) {perror("sigprocmask");return 1;}printf("SIGINT is unblocked.\n");return 0;
}

sigpending系统调用

  • 函数原型int sigpending(sigset_t *set);
  • 作用:获取当前进程中已产生但被阻塞(挂起)的信号集,并将其存储在 set 指向的信号集中。
  • 返回值:成功时返回 0,失败时返回 -1,并设置 errno 以指示错误原因

示例代码

#include <stdio.h>
#include <signal.h>
#include <unistd.h>int main() {sigset_t new_mask, pending_mask;sigemptyset(&new_mask);sigaddset(&new_mask, SIGINT);// 阻塞SIGINT信号if (sigprocmask(SIG_BLOCK, &new_mask, NULL) == -1) {perror("sigprocmask");return 1;}// 获取挂起的信号集if (sigpending(&pending_mask) == -1) {perror("sigpending");return 1;}if (sigismember(&pending_mask, SIGINT)) {printf("SIGINT is pending.\n");} else {printf("SIGINT is not pending.\n");}sleep(3);// 获取挂起的信号集if (sigpending(&pending_mask) == -1) {perror("sigpending");return 1;}if (sigismember(&pending_mask, SIGINT)) {printf("SIGINT is pending.\n");} else {printf("SIGINT is not pending.\n");}// 解除对SIGINT信号的阻塞if (sigprocmask(SIG_UNBLOCK, &new_mask, NULL) == -1) {perror("sigprocmask");return 1;}return 0;
}

被挂起的信号

        在执行设置阻塞后与解除阻塞前这两者间的代码时,如果收到要被阻塞的信号,该信号会被挂起。在解除阻塞后,该信号会被发送给进程,来执行该信号默认的处理动作。需要注意的是,无论阻塞了几次相同的信号,该信号阻塞在被解除后,该信号都只会被触发一次。

进程掩码与sigaction

        不是很清楚sigaction的同学可以看进程信号之sigaction系统调用-CSDN博客
        sigprocmask设置的进程掩码是对整个进程的时时刻刻来讲的;sigaction中也要设置一个信号集,用作设置阻塞信号,但是这个阻塞信号是对sigaction所针对的特定信号的处理逻辑执行时来讲的,只有在这个触发这个信号的处理逻辑时才会阻塞这个信号集。
        sigaction中要阻塞的信号确切地说是sigaction中设置的信号集与进程掩码的并集。这一点在大家充分理解进程掩码与sigaction系统调用的基础上,不难理解。

http://www.xdnf.cn/news/988651.html

相关文章:

  • QMultiMapQHashQList使用区别
  • 中学教资考试面试回忆
  • 学车笔记 变挡
  • 图数据库的理解
  • Python打卡第51天
  • n8n部署步骤
  • AI Engine Kernel and Graph Programming--知识分享9
  • PostgreSQL --数据库操作
  • libyuv的三种缩放模式
  • Verilog:流水线乘法器
  • 【热更新知识】学习三 XLua学习
  • 我们来学mysql -- 8.4版本记录慢查询
  • 1.对结构学习的整体构想
  • 教师端用户操作手册
  • Smartbi双产品线功能更新:主动分析更省心,数据治理更高效
  • tableau 实战工作场景专业仪表盘的搭建(整体思路)详解
  • CMake指令:aux_source_directory
  • RFID测温芯片在新能源电池管理中的创新应用
  • 11. 线性表的顺序表示和实现(3)
  • AI视频生成API:一站式视频生成解决方案
  • JAVA(Day_4
  • 网络管理【Linux/Unix/Windows】命令大全
  • 保障信号纯净:线材滤波器在复杂电磁环境中的作用
  • Java 8 Stream 流全面使用教程 - 完整版
  • 肩胛骨髓外浸润
  • Android11 Launcher3实现去掉抽屉改为单层
  • 汇编(cpu寄存器描述)
  • 字符串和内存函数(2)
  • MacBook M1 Pro下载安装MySql
  • Redis分布式缓存(RDB、AOF、主从同步)