15 - 信号处理设计模式

---- 整理自狄泰软件唐佐林老师课程

查看所有文章链接:(更新中)Linux系统编程训练营 - 目录

文章目录

  • 1. Linux应用程序安全性讨论
    • 1.1 问题
    • 1.2 不同场景
      • 1.2.1 场景一:不需要处理信号
      • 1.2.2 场景二:需要处理信号
  • 2. 场景一:不需要信号处理(单一功能应用程序)
  • 3. 场景二:需要处理信号(长时间运行的应用)
    • 3.1 同步解决方案(单任务)
      • 3.1.1 方案设计一
        • 3.1.1.1 同步方案示例一
        • 3.1.1.2 编程实验
        • 3.1.1.3 存在的问题
      • 3.1.2 方案设计二
        • 3.1.2.1 关键系统函数
        • 3.1.2.2 编程实验
        • 3.1.2.3 存在的问题
        • 3.1.2.4 思考
    • 3.2 异步解决方案(多任务)
      • 3.2.1 问题
      • 3.2.2 多线程信号处理
      • 3.2.3 方案
      • 3.2.4 进程与线程
        • 3.2.4.1 Linux多线程API函数
        • 3.2.4.2 多线程编程示例
      • 3.2.5 异步方案示例
      • 3.2.6 编程实验:多线程信号处理
  • 4. 信号设计模式小结

1. Linux应用程序安全性讨论

1.1 问题

  • 如何编写信号安全的应用程序?

1.2 不同场景

1.2.1 场景一:不需要处理信号

应用程序实现单一功能,不需要关注信号
如:数据处理程序,文件加密程序,科学计算程序

1.2.2 场景二:需要处理信号

应用程序长时间运行,需要关注信号,并及时处理
如:服务端程序,上位机程序

2. 场景一:不需要信号处理(单一功能应用程序)

在代码层面,直接阻塞所有可能的信号(本质上就是信号始终处于未决状态,无法递达进程)

在这里插入图片描述

  • 编程实验:不需要处理信号

【参看链接】:15 - 信号处理设计模式 / 00不需要处理信号场景/main.c

在这里插入图片描述
在这里插入图片描述

3. 场景二:需要处理信号(长时间运行的应用)

  • 同步方案
    • 通过 标记 同步处理信号,整个应用中 只有一个执行流
  • 异步方案
    • 专用任务处理,应用中存在 多个执行流(多线程应用)
    • 设置 专用于信号处理的任务,其它任务忽略信号,专注功能实现

3.1 同步解决方案(单任务)

  • 信号处理逻辑与程序逻辑位于同一个上下文
    即:信号处理函数与主函数不存在资源竞争关系

3.1.1 方案设计一

  1. 将任务分解为 子任务(每个任务可对应一个函数)
  2. 信号递达时,信号处理函数中 标记 递达状态
  3. 子任务处理结束后,真正执行信号处理

在这里插入图片描述

3.1.1.1 同步方案示例一

在这里插入图片描述

3.1.1.2 编程实验

【参看链接】:15 - 信号处理设计模式 / 01处理信号场景_同步方案

  1. 对于不可靠信号

在这里插入图片描述
在这里插入图片描述

  1. 对于可靠信号存在问题

在这里插入图片描述
在这里插入图片描述
在这里插入图片描述

3.1.1.3 存在的问题

  • 由于给每个信号唯一的标记位置,因此,所有信号转变为不可靠信号,并且仅保留最近递达的信号信息。
  • 可能改进方案:
    • 标记位置设计为链表,信号递达后在对应位置的链表处增加结点保留信号信息
      (增加结点涉及到malloc,不安全)

3.1.2 方案设计二

  1. 将任务分解为子任务(每个任务可对应一个函数)
  2. 创建 信号文件描述符,并阻塞所有信号(可靠信号递达前位于内核队列)
    • 意义:化被动为主动,原先任务的执行流在收到信号后被动中断。现在主动去检查是否有信号,如果有信号,将信号取出来处理,此时就需要文件描述符。
  3. 子任务处理结束后,通过 select机制 判断是否有信号需要处理
    • true:处理信号,false:等待超时

3.1.2.1 关键系统函数

在这里插入图片描述

  • 使用signalfd()处理信号
    先屏蔽所有信号(无法递达进程),之后为屏蔽信号创建文件描述符,当时机成熟,通过read()系统调用读取未决信号(主动接收信号)。

在这里插入图片描述

  • 使用select()监听文件描述符

在这里插入图片描述

  • 使用select()处理信号

在这里插入图片描述

3.1.2.2 编程实验

【参看链接】:15 - 信号处理设计模式 / 02处理信号场景_同步方案_select

  1. 可靠信号

在这里插入图片描述
在这里插入图片描述
在这里插入图片描述

  1. 不可靠信号

在这里插入图片描述
在这里插入图片描述

3.1.2.3 存在的问题

  • 虽然解决了信号丢失的问题,但是实时性不好。由于使用了select()机制,即便没有信号需要处理,也需要等待select超时,任务 实时性 受到影响

在这里插入图片描述

3.1.2.4 思考

  • 是否可以兼顾 信号处理任务执行 的实时性?

3.2 异步解决方案(多任务)

  • 使用独立任务处理信号,程序逻辑在其它任务中执行
    即:通过 多线程 分离信号处理与程序逻辑
    • 主线程:专用于处理信号
    • 其它线程:完成程序功能

3.2.1 问题

  • 信号递达进程后,在 哪一个执行流 中进行处理?

3.2.2 多线程信号处理

  • 信号的发送目标是 进程,而不是某个特定的线程
  • 发送给进程的信号仅递送给一个线程 ==> 哪一个线程处理?
  • 内核在不会阻塞目标信号的线程中进行随机选择
  • 每个线程拥有独立的信号屏蔽掩码

3.2.3 方案

  • 主线程:对目标信号设置信号处理的方式
    • 当信号递达进程时,只可能是 主线程 进行信号处理
  • 其它线程:首先屏蔽所有可能的信号(简单粗暴),之后执行任务代码
    • 无法接收到信号,不具备信号处理能力

3.2.4 进程与线程

  • 进程:应用程序的一次加载执行(系统进行资源分配的基本单位)
  • 线程:进程中的程序执行流
    • 一个进程可以存在多个线程(至少存在一个线程)
    • 每个线程执行不同的任务(多个线程可并行执行)
    • 同一个进程中的多个线程共享进程的系统资源

3.2.4.1 Linux多线程API函数

在这里插入图片描述

  • 线程标识:pthread_t pthread_self(void);
    • 获取当前线程的ID标识(tid)
  • 线程等待:int pthread_join(pthread_t thread, void** retval);
    • 等待目标线程执行结束

3.2.4.2 多线程编程示例

在这里插入图片描述

3.2.5 异步方案示例

  1. 主线程

在这里插入图片描述

  1. 任务线程

在这里插入图片描述

3.2.6 编程实验:多线程信号处理

【参看链接】:15 - 信号处理设计模式 / 03处理信号场景_异步方案_多线程

  1. 不可靠信号

在这里插入图片描述
在这里插入图片描述

  1. 可靠信号

在这里插入图片描述
在这里插入图片描述
在这里插入图片描述

4. 信号设计模式小结

  • 多数程序不需要处理信号,因此可直接屏蔽信号
  • 需要处理信号的程序,重点考虑信号安全性问题
    • 同步 处理方案,通过设计让 任务代码信号处理代码 交替执行
      问题:信号处理是否及时?任务执行是否实时?
    • 异步 处理方案,任务代码信号处理代码 位于 不同执行流
      问题:将信号安全性问题转换为线程安全性问题,因此,程序本身是否做到线程安全?

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

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

相关文章

部署LAMP 平台(二十四)

提示:文章写完后,目录可以自动生成,如何生成可参考右边的帮助文档 目录 前言 一、概述 二、PHP安装配置 1. PHP的作用 2. PHP安装 2.1 yum安装 2.2 PHP语言简介 三、安装 四、启动 五、书写测试页面 六、客户端访问 七、书写连接数据库页…

龙迅LT8711HE DP/Type-C输入转HDMI2.0

LT8711HE是一款高性能C/DP1.2到HDMI2.0转换器,设计用于将USB C型源或DP1.2源连接到HDMI2.0接收器。 LT8711HE集成了DP1.2兼容接收机和HDMI2.0兼容发射机。此外,还包括两个CC控制器,用于CC通信,以实现DP-Alt模式和电源输送功能&…

微服务系列文章之 Redisson实现分布式锁(3)

一、概述 1、技术架构 项目总体技术选型 SpringBoot2.4.5 Maven3.5.4 Redisson3.5.4 lombok(插件)2、加锁方式 该项目支持 自定义注解加锁 和 常规加锁 两种模式 自定义注解加锁 DistributedLock(value"goods", leaseTime5)public String lockDecreaseStock(…

8、链路层以太网协议,ARP协议32

网络层IP协议描述了通信中的起点到终点,但是数据不是飞过去的,是经过了大量的中间节点转发完成的。 一、以太网协议 1、MAC地址 物理硬件地址,是每一块网卡在出厂时设定的地址,固定且不可修改(早期,现在可…

C语言模拟实现字符串处理函数

需要多一点点勇气,来面对变差的自己 大家好,我是纪宁。 这篇文章为大家带来的是5大字符串处理函数的模拟实现。 文章目录 1.strlen函数的模拟实现 2.strcpy函数的模拟实现 3.strcmp函数的模拟实现 4.strcat函数的模拟实现 5.strstr函数的模拟实现…

软件测试|SQL常用语法,你都会吗?

前言 SQL作为一门语言,和其他编程语言一样,都是需要遵循一些特定的规范和准则的,这也就是我们常说的语法(Syntax)。 下面是几个SQL的语法规则: 所有的 SQL 语法都必须以关键字(也称命令&…

04-spring配置文件加载过程

文章目录 spring配置文件加载过程 spring配置文件加载过程 调用refresh方法中obtainFreshBeanFactory() Overridepublic void refresh() throws BeansException, IllegalStateException {synchronized (this.startupShutdownMonitor) {// Prepare this context for refreshing.…

我们如何在 Elasticsearch 8.6、8.7 和 8.8 中加速数据摄入

作者:Adrien Grand, Joe Gallo, Tyler Perkins 正如你们中的一些人已经注意到的,Elasticsearch 8.6、8.7 和 8.8 在各种数据集上带来了良好的索引加速,从简单的关键字到繁重的 KNN 向量,以及摄取管道繁重的摄取工作负载。 摄取涉及…

推荐10个Flutter开源项目

作为跨平台应用开发的领头羊,Flutter从已发布就受到广大开发者的追捧。使用Flutter技术开发的应用不仅体验上无限接近原生应用,在开发效率上也是其他技术无法比拟的。随着其开发者社区的不断壮大,Flutter生态系统已经相当强大,并且众多开源应用程序也相继诞生。这些开源应用…

ceph--cephFS的使用

ceph分布式存储—cephFS的使用 1、cephfs的概念 ceph FS 即 ceph filesystem,可以实现文件系统共享功能,客户端通过 ceph 协议挂载并使 用 ceph 集群作为数据存储服务器。 Ceph FS 需要运行 Meta Data Services(MDS)服务,其守护进程为 ceph-mds&#x…

MongoDB

安装 数据存放路径:D:\data\db 安装目录:D:\MongoDB\mongodb-windows-x86_64-5.0.19\mongodb-win32-x86_64-windows-5.0.19\bin 配置环境变量 开启服务端,客户端 # 开启服务端,指定数据存放路径 mongod --dbpath D:\data\…

【HCIA】11.ACL与NAT地址转换

ACL 通过ACL可以实现对网络中报文流的精确识别和控制,达到控制网络访问行为、防止网络攻击和提高网络带宽利用率的目的。 ACL是由permit或deny语句组成的一系列有顺序的规则的集合;它通过匹配报文的相关字段实现对报文的分类。ACL是能够匹配一个IP数据包…