15 - 信号处理设计模式

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

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

文章目录

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

  • 多数程序不需要处理信号,因此可直接屏蔽信号
  • 需要处理信号的程序,重点考虑信号安全性问题
    • 同步 处理方案,通过设计让 任务代码信号处理代码 交替执行
      问题:信号处理是否及时?任务执行是否实时?
    • 异步 处理方案,任务代码信号处理代码 位于 不同执行流
      问题:将信号安全性问题转换为线程安全性问题,因此,程序本身是否做到线程安全?
相关推荐
HLC++5 小时前
Linux的进程间通信
android·linux·服务器
华清远见IT开放实验室7 小时前
实验室建设案例 | 石家庄科技信息职业学院嵌入式实验室——从底层硬件到系统应用,一所应用型高校的嵌入式人才培养这样落地
linux·arm开发·stm32·嵌入式硬件·高校·实验室建设
groundhappy9 小时前
idalib安装和codex ida-mcp配置
linux·开发语言·python
通信小小昕10 小时前
Ubuntu 26.04 中文输入法安装
linux·运维·ubuntu
张小姐的猫11 小时前
【Linux】网络编程 —— HTTP协议(上)
linux·运维·服务器·网络·http·单例模式·策略模式
栩栩云生11 小时前
AI 写代码犯的错,早被写进了错题集
linux·安全·ai编程
imc.1113 小时前
linux基础IO
linux·运维·服务器
杨充14 小时前
10.可测试性实战设计
设计模式·开源·代码规范
杨充14 小时前
9.重构十二式的实战
设计模式·开源·代码规范
杨充14 小时前
6.设计原则的全景图
设计模式·开源·全栈