sigfillset 函数详解

sigfillset 函数详解

一、函数概念

sigfillset() 是 POSIX 信号处理中的核心函数,用于初始化并填充一个信号集,使其包含当前系统支持的所有信号。它是操作信号屏蔽字(signal mask)的基础工具,常与 sigprocmask()sigsuspend() 等函数配合使用。

关键特性:
  • 初始化信号集:将 sigset_t 类型变量设为包含所有信号
  • 原子操作:保证线程安全
  • 不可阻塞信号:对 SIGKILLSIGSTOP 无效(这两个信号永远不可阻塞)

二、函数原型和头文件

#include <signal.h>int sigfillset(sigset_t *set);
参数:
  • set:指向要填充的信号集的指针
返回值:
  • 成功:返回 0
  • 失败:返回 -1 并设置 errno(通常是 EFAULT,表示无效指针)

三、信号集(sigset_t)详解

信号集是用于表示一组信号的数据类型,本质是位掩码(bitmask)。在 Linux 中通常定义为:

typedef struct {unsigned long sig[_NSIG_WORDS];
} sigset_t;
信号范围:
  • 标准信号:1~31(如 SIGINT=2, SIGSEGV=11
  • 实时信号:32~64(SIGRTMINSIGRTMAX

使用 kill -l 命令可查看系统支持的信号列表


四、使用场景

1. 阻塞所有信号
sigset_t all_signals;
sigfillset(&all_signals);  // 填充所有信号// 设置进程信号屏蔽字
sigprocmask(SIG_SETMASK, &all_signals, NULL);
2. 安全临界区保护
void critical_section() {sigset_t old_set, new_set;// 准备阻塞所有信号sigfillset(&new_set);// 进入临界区前阻塞信号sigprocmask(SIG_SETMASK, &new_set, &old_set);/* 临界区代码(不会被任何信号中断) */// 恢复原始信号屏蔽sigprocmask(SIG_SETMASK, &old_set, NULL);
}
3. 等待特定信号
sigset_t mask, original_mask;
sigfillset(&mask);          // 包含所有信号
sigdelset(&mask, SIGUSR1);  // 删除 SIGUSR1// 阻塞除 SIGUSR1 外的所有信号
sigprocmask(SIG_SETMASK, &mask, &original_mask);// 等待 SIGUSR1 信号
sigsuspend(&mask);// 恢复原始信号屏蔽
sigprocmask(SIG_SETMASK, &original_mask, NULL);

五、完整使用示例

示例:安全信号处理框架
#include <signal.h>
#include <stdio.h>
#include <unistd.h>volatile sig_atomic_t flag = 0;void handler(int sig) {flag = 1;  // 仅设置标志(异步安全)
}int main() {// 配置信号处理struct sigaction sa;sa.sa_handler = handler;sigemptyset(&sa.sa_mask);sa.sa_flags = SA_RESTART;sigaction(SIGINT, &sa, NULL);// 准备信号集sigset_t all_signals, wait_mask;sigfillset(&all_signals);      // 包含所有信号sigemptyset(&wait_mask);       // 空信号集sigaddset(&wait_mask, SIGINT); // 只关注SIGINT// 阻塞除SIGINT外的所有信号sigset_t old_mask;sigprocmask(SIG_SETMASK, &all_signals, &old_mask);sigdelset(&all_signals, SIGINT); // 允许SIGINT传递while(1) {// 安全等待信号(原子操作)sigsuspend(&wait_mask);if(flag) {printf("Processing signal...\n");/* 安全处理逻辑(非异步安全函数放这里) */flag = 0;}}// 恢复原始信号屏蔽(实际不会执行到这里)sigprocmask(SIG_SETMASK, &old_mask, NULL);return 0;
}

六、相关函数对比

函数功能常见使用场景
sigfillset()填充所有信号到信号集初始化全局屏蔽
sigemptyset()清空信号集准备添加特定信号
sigaddset()添加单个信号到信号集自定义屏蔽组合
sigdelset()从信号集删除单个信号允许特定信号通过
sigismember()检查信号是否在集合中信号状态判断
sigprocmask()设置进程信号屏蔽字临界区保护/信号阻塞
sigsuspend()临时替换信号掩码并等待信号原子等待操作

七、重要注意事项

  1. 信号集生命周期

    // 错误!未初始化信号集
    sigset_t set;
    sigprocmask(SIG_SETMASK, &set, NULL); // 未定义行为// 正确:必须显式初始化
    sigset_t set;
    sigfillset(&set); // 或 sigemptyset(&set);
    
  2. 不可阻塞信号

    sigset_t set;
    sigfillset(&set);
    sigprocmask(SIG_SETMASK, &set, NULL);// 以下信号仍能终止进程
    kill(getpid(), SIGKILL); // 始终有效
    kill(getpid(), SIGSTOP); // 始终有效
    
  3. 线程安全

    • 在多线程环境中,使用 pthread_sigmask() 替代 sigprocmask()
    pthread_sigmask(SIG_SETMASK, &set, NULL);
    
  4. sigaction 协作

    struct sigaction sa;
    sa.sa_handler = handler;
    sigfillset(&sa.sa_mask);  // 执行处理函数时阻塞所有其他信号
    sa.sa_flags = 0;
    

八、错误处理

sigset_t signal_set;if (sigfillset(&signal_set) == -1) {perror("sigfillset failed");switch(errno) {case EFAULT:fprintf(stderr, "Invalid memory address\n");break;default:fprintf(stderr, "Unknown error\n");}exit(EXIT_FAILURE);
}

总结

sigfillset() 是 Linux 信号处理的基础构建块:

  1. 核心作用:快速初始化包含所有信号的信号集
  2. 典型应用
    • 创建全局信号屏蔽
    • 实现安全临界区
    • 配合 sigsuspend() 实现原子等待
  3. 最佳实践
    • 总是显式初始化信号集
    • 结合 sigdelset() 实现精细控制
    • 在多线程程序中使用线程安全版本

掌握 sigfillset() 及其相关函数,是编写健壮的信号处理代码的关键一步。通过合理控制信号屏蔽,可以有效防止信号竞争条件和不可预知的中断行为。

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。
如若转载,请注明出处:http://www.pswp.cn/diannao/94642.shtml
繁体地址,请注明出处:http://hk.pswp.cn/diannao/94642.shtml

如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈email:809451989@qq.com,一经查实,立即删除!

相关文章

Redis实战(8) -- 分布式锁Redission底层机制

介绍Redisson 是基于 Redis 实现的 Java 驻内存数据网格&#xff08;In-Memory Data Grid&#xff09;&#xff0c;提供了分布式和可扩展的 Java 数据结构&#xff0c;如分布式锁、分布式集合等。【注意】如果需要重新实现redission&#xff0c;需要重新设置RedissionClient配置…

Linux基础测试

linux基础测试 一、环境准备 基础环境信息 登录用户&#xff1a;root&#xff08;初始密码&#xff1a;redhat&#xff09; 虚拟机启动&#xff1a;登录后执行 virt-manager&#xff0c;右键启动 node1 和 node2 虚拟机 node1 信息&#xff1a;root 密码为 redhat&#xf…

Linux中Docker Swarm实践

一、部署前后分离使用你自己的自定义镜像部署多个副本所有副本使用相同的配置和逻辑Nginx 做反向代理统一入口外部访问形式如&#xff1a;http://your-domain/api/xxx1.1 建立私库镜像已构建并推送到可访问的镜像仓库启动 Docker Registry 容器docker run -d -p 5000:5000 --re…

Dash 中的 dcc.Clipboard 组件详解:实现一键复制功能

dcc.Clipboard 是 Dash 核心组件库中的一个实用工具&#xff0c;允许用户将指定内容一键复制到系统剪贴板&#xff0c;极大提升用户体验。本文将深入解析该组件的用法、特性和实际应用场景。 一、组件核心功能与价值 dcc.Clipboard 解决了 Web 应用中的关键痛点&#xff1a; 简…

初识C++类的6个默认成员函数

目录 一、初始化和清理 二、拷贝复制 三、取地址重载 四、重要说明 五、注意事项 六、示例代码 在C中&#xff0c;当一个类没有显式定义某些成员函数时&#xff0c;编译器会自动生成6个默认成员函数。这些函数可以分为以下几类&#xff1a; 一、初始化和清理 1、构造函数…

Spring事务失效场景?

题目详细答案Spring事务失效的场景主要有以下几种。非public方法使用Transactional场景描述&#xff1a;Spring事务管理是基于AOP实现的&#xff0c;而AOP对于JDK动态代理或CGLib动态代理只会代理public方法。如果事务方法的访问修饰符为非public&#xff0c;SpringAOP无法正确…

1.电动汽车动力电池系统技术介绍与分类

1.电动汽车动力电池系统技术介绍与分类 1.1 电动汽车发展的三个 “黄金时代” 第一个黄金时代&#xff08;19 世纪末 - 20 世纪初&#xff09; 技术基础&#xff1a;铅酸蓄电池发明&#xff08;1859 年&#xff09;&#xff0c;推动电动三轮车&#xff08;1873 年&#xff09;、…

调用阿里云-阿里云百炼 AI

相关文档&#xff1a;大模型服务平台百炼控制台 多轮对话&#xff1a;通义千问模型的多轮对话_大模型服务平台百炼(Model Studio)-阿里云帮助中心 创建知识库&#xff1a;大模型服务平台百炼控制台 创建智能体&#xff1a;大模型服务平台百炼控制台 点击智能体发布后&#x…

Apache Flink:从实时数据分析到实时AI

引言欢迎踏上这段深入了解 Apache Flink 演进历程的旅程&#xff0c;Apache Flink 是一项重新定义了实时数据处理的技术。本博客文章基于王峰&#xff08;阿里云开放数据平台负责人、Apache Flink Committer&#xff09;在 2025 年 Flink Forward Asia 新加坡大会上的演讲内容编…

oelove奥壹新版v11.7旗舰版婚恋系统微信原生小程序源码上架容易遇到的几个坑,避免遗漏参数白屏显示等问题

oelove和 金媒我都用过一段时间&#xff0c;其中oelove 用的时间较多&#xff0c;也比较了解这个系统&#xff0c;这个系统比较不错的就是小程序是原生的&#xff08;完全遵循微信开发者平台规则非Uniapp&#xff09;开发的&#xff0c;原生小程序的特点就是兼容性好&#xff0…

行为模式-模板方法模式

定义&#xff1a;Define the skeleton of an algorithm in an operation,deferring some steps to subclasses.Template Method lets subclasses redefine certain steps of an algorithm without changing the algorithms structure.&#xff08;定义一个操作中的算法的框架&a…

Java集合遍历练习题

以下是10道难度递增的集合遍历练习题&#xff0c;涵盖List、Set、Map的各种遍历方式&#xff0c;包含解题思路、代码实现和输出结果&#xff1a; 练习题1&#xff1a;基础遍历 - ArrayList的for-each遍历 题目&#xff1a;创建一个存储5个字符串的ArrayList&#xff08;元素为&…

深度学习·ZegclipClip-RC

Zegclip 获取图像的特殊编码&#xff1a;使用prompt tuning的技术&#xff0c;目的是减少过拟合和计算量。调整文本编码&#xff1a;使用RD关系描述符&#xff0c;将每一个文本对应的[cls] token和图像对应的[cls] token作哈密顿积&#xff0c;最后文本[cls]token形式化任务 文…

Taro 扩展 API 深度解析与实战指南

Taro 扩展 API 深度解析与实战指南 Taro 作为一款优秀的多端开发框架&#xff0c;提供了一系列强大的扩展 API&#xff0c;这些 API 极大地提升了开发效率和应用的可维护性。本文将深入解析 Taro 的扩展 API&#xff0c;并根据其功能特性进行分类讲解&#xff0c;帮助开发者更…

容器之王--Docker的部署及基本操作演练

1.2 部署docker 1.2.1 容器工作方法1.2.2 部署第一个容器 官方站点&#xff1a;https://docs.docker.com/ 1.2.2.1 配置软件仓库 ]# cd /etc/yum.repos.d ]# vim docker.repo [docker] name docker-ce baseurl https://mirrors.aliyun.com/docker-ce/linux/rhel/9/x86_64/sta…

VFTO与局部放电-高压设备绝缘系统的双重挑战与防护策略

目录 引言VFTO的定义与形成机理VFTO对高压设备绝缘系统的影响局部放电的危害与机制VFTO与局部放电的关联性分析检测与监测技术防护与抑制措施未来技术发展趋势结论与展望引言 在现代电力系统中&#xff0c;超快速暂态过电压&#xff08;Very Fast Transient Overvoltage, VFTO&…

Windows下Rust编码实现MP4点播服务器

Rust编码可以实现众多简洁、可靠、高效的应用&#xff0c;但语法逻辑要求严格&#xff0c;尤其是依赖库的选择调用&#xff0c;需要耐心坚持“推敲”。借助DeepSeek并反复编程调试和问答改进&#xff0c;可以最终得到完整有效的Rust编码。下面分享Windows下Rust编码实现MP4点播…

ubuntu-相关指令

1、串口1.1确认在系统中检查设备是否正常加载&#xff0c;在终端输入以下命令&#xff1a;way1&#xff1a;ll /dev | grep ttyUSB&#xff08;ll是LL的小写&#xff09; way2&#xff1a;ll /dev | grep ttyACM way3&#xff1a;ll /dev | grep ttyCH343USB&#…

docker容器临时文件去除,服务器容量空间

概述&#xff1a; 接到告警提醒&#xff0c;服务器容量不足&#xff0c;去查看了一下&#xff0c;发现确实100g左右容量已基本用完&#xff1b;分析&#xff1a; 1&#xff09;查看根目录下哪些文件夹占用容量较大 使用命令“ du -ah --max-depth1 / ” 查看目标目录下所有文件…

损耗对信号质量的影响

损耗通常分为介质损耗与导体损耗&#xff1a;介质损耗&#xff1a;介质被施加电场后介质内部带电粒子在外加电场的作用力下进行微小移动介质损耗与频率成正比导体损耗&#xff1a;导体由于存在电阻&#xff0c;在有电流流过时产生的热量造成的损耗为导体损耗。同时&#xff0c;…