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

Linux系统 异常控制流

文章目录

  • 前言
  • 异常
    • 1. **中断(interrupt)**
    • 2. **陷阱和系统调用(trap)**
    • 3. **故障(fault)**
    • 4. **终止(abort)**
  • 进程与信号
  • 非本地跳转

前言

下面内容大部分来自《深入理解计算机系统》(CSAPP)一书第八章异常控制流,更深入了解建议阅读此书第八章,推荐阅读《UNIX高级环境编程》。

异常控制流(Exception Control Flow, ECF) 是计算机系统中用来处理非正常情况的一种控制流方式。它允许程序在遇到错误或异常事件时,从正常的程序执行路径中跳出,执行特殊的处理逻辑,然后恢复正常流程或者终止程序。这种机制在操作系统、编程语言和硬件层面都有广泛应用。

异常

异常是异常控制流的一种形式,它一部分由硬件实现,一部分由操作系统实现。因为它们有一部分是由硬件实现的,所以具体细节将随系统的不同而有所不同。然而,对于每个系统而言,基本的思想都是相同的。

异常(exception)就是控制流中的突变,用来响应处理器状态中的某些变化。

在这里插入图片描述

在任何情况下,当处理器检测到有事件发生时,它就会通过一张叫做异常表(exception table)的跳转表,进行一个间接过程调用(异常),到一个专门设计用来处理这类事件的操作系统子程序(异常处理程序(exception handler)).当异常处理程序完成处理后,根据引起异常的事件的类型,会发生以下 3 种情况中的一种:

  1. 处理程序将控制返回给当前指令Icurr,即当事件发生时正在执行的指令。
  2. 处理程序将控制返回给 Inext ,如果没有发生异常将会执行的下一条指令。
  3. 处理程序终止被中断的程序。

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

异常类别

类别原因异步/同步返回行为
中断来自 I/O 设备的信号异步总是返回到下一条指令
陷阱有意的异常同步总是返回到下一条指令
故障潜在可恢复的错误同步可能返回到当前指令
终止不可恢复的错误同步不会返回

1. 中断(interrupt)

中断是一种由外部硬件设备发出的异步信号,用于引起 CPU 暂停当前执行的程序,去处理外部事件。中断机制的核心在于提供一种高效的方式来响应外部设备的请求,而不需要程序主动轮询设备的状态。

在这里插入图片描述

2. 陷阱和系统调用(trap)

陷阱是一种由程序主动触发的同步异常,用于请求操作系统的服务(例如系统调用)或进入调试模式。陷阱的目的是通过特定指令让程序安全地从用户模式切换到内核模式,从而执行特权操作。

在这里插入图片描述

3. 故障(fault)

故障是一种由程序触发的同步异常,表示某些潜在错误需要立即处理。故障的处理机制允许操作系统尝试修复问题,使程序可以恢复并继续执行。

在这里插入图片描述

4. 终止(abort)

终止是一种不可恢复的异常,通常由硬件或系统检测到的致命错误触发。这种错误表示程序或系统的状态已经严重损坏,无法继续运行。

在这里插入图片描述

进程与信号

由于进程与信号部分过长,我将这两部分分开写成两篇,详见Linux系统 进程和Linux系统 信号。

非本地跳转

非本地跳转是一种控制转移机制,能够从一个函数直接跳转到另一个函数中的特定位置,且这种跳转跨越了函数调用栈的正常层次结构,不遵循常规的函数调用和返回顺序。它将控制直接从一个函数转移到另一个当前正在执行的函数,而不需要经过正常的调用—返回序列。非本地跳转是通过 setjmplongjmp 函数来提供的。

#include <setjmp.h>int setjmp(jmp_buf env);
int sigsetjmp(sigjmp_buf env, int savesigs);
// 返回:setjmp 返回 0,longjmp 返回非零。

setjmp 函数在 env 缓冲区中保存当前调用环境,以供后面的 longjmp 使用,并返回 0。调用环境包括程序计数器、栈指针和通用目的寄存器。setjmp 返回的值不能被赋值给变量:rc = setjmp(env); /* Wrong! */

#include <setjmp.h>void longjmp(jmp_buf env, int retval);
void siglongjmp(sigjmp_buf env, int retval);
// 从不返回。

longjmp 函数从 env 缓冲区中恢复调用环境,然后触发一个从最近一次初始化 env 的 setjmp 调用的返回。然后 setjmp 返回,并带有非零的返回值 retval。

jmp_buf buf;int error1 = 0;
int error2 = 1;void foo(void), bar(void);int main()
{switch (setjmp(buf)) {case 0:foo();break;case 1:printf("Detected an error1 condition in foo\n");break;case 2:printf("Detected an error2 condition in foo\n");break;default:printf("Unknown error condition in foo\n");}exit(0);
}/* Deeply nested function foo */
void foo(void)
{if (error1)longjmp(buf, 1);bar();
}void bar(void)
{if (error2)longjmp(buf, 2);
}

main 函数首先调用 setjmp 以保存当前的调用环境,然后调用函数 foo,foo 依次调用函数 bar。如果 foo 或者 bar 遇到一个错误,它们立即通过一次 longjmp 调用从 setjmp 返回。setjmp 的非零返回值指明了错误类型,随后可以被解码,且在代码中的某个位置进行处理。

C++ 和 Java 中的软件异常

C++ 和 Java 提供的异常机制是较高层次的,是 C 语言的 setjmp 和 longjmp 函数的更加结构化的版本。可以把 try 语句中的 catch 子句看做类似于 setjmp 函数。相似地,throw 语句就类似于 longjmp 函数。

异常控制流(ECF)发生在计算机系统的各个层次,是计算机系统中提供并发的基本机制。

在硬件层,异常是由处理器中的事件触发的控制流中的突变。控制流传递给一个软件处理程序,该处理程序进行一些处理,然后返回控制给被中断的控制流。
有四种不同类型的异常:中断、故障、终止和陷阱。当一个外部 I/O 设备(例如定时器芯片或者磁盘控制器)设置了处理器芯片上的中断管脚时,(对于任意指令)中断会异步地发生。控制返回到故障指令后面的那条指令。一条指令的执行可能导致故障和终止同步发生。故障处理程序会重新启动故障指令,而终止处理程序从不将控制返回给被中断的流。最后,陷阱就像是用来实现向应用提供到操作系统代码的受控的人口点的系统调用的函数调用。
在操作系统层,内核用 ECF 提供进程的基本概念。进程提供给应用两个重要的抽象:

  • 逻辑控制流,它提供给每个程序一个假象,好像它是在独占地使用处理器;
  • 私有地址空间,它提供给每个程序一个假象,好像它是在独占地使用主存。
    在操作系统和应用程序之间的接口处,应用程序可以创建子进程,等待它们的子进程停止或者终止,运行新的程序,以及捕获来自其他进程的信号。信号处理的语义是微妙的,并且随系统不同而不同。然而,在与 Posix 兼容的系统上存在着一些机制,允许程序清楚地指定期望的信号处理语义。

最后,在应用层,C 程序可以使用非本地跳转来规避正常的调用/返回栈规则,并且直接从一个函数分支到另一个函数。


http://www.mrgr.cn/news/78643.html

相关文章:

  • C++ 之弦上舞:string 类与多样字符串操作的优雅旋律
  • AI开发 - GPT之魂 用Python 演示chatGPT的自注意力机制 - 机器学习
  • 数据并行、模型并行与张量并行:深度学习中的并行计算策略(中英双语)
  • 黄小宁关于初等数学短文的重赏启事
  • 【linux学习指南】Linux进程信号产生(二)软件中断
  • AI与ArcGIS Pro的地理空间分析和可视化
  • 【CSS in Depth 2 精译_064】10.3 CSS 中的容器查询相对单位 + 10.4 CSS 容器样式查询 + 10.5 本章小结
  • 【连接池】.NET开源 ORM 框架 SqlSugar 系列
  • C_字符串其实就是字符数组
  • pcb线宽与电流
  • win10系统安装docker-desktop
  • 6.STM32之通信接口《精讲》之IIC通信---硬件IIC(STM32自带的硬件收发器)
  • 扩散模型_Diffusion Model
  • ffmpeg安装(windows)
  • 链表?->?(以尾插法说明,附头插法)
  • 输入一行字符,分别统计出其中英文字母、空格、数字和其它字符的个数。-多语言
  • STL——string类的模拟实现
  • 基于 Spring Boot 实现图片的服务器本地存储及前端回显
  • Matlab学习笔记
  • Ionic移动端开发
  • FFmpeg 推流给 FreeSWITCH
  • ESP32开发板在micropython里直接用requests向web服务器发送请求:ESP32S3开发板通过fastapi中转成功连接星河大模型
  • 判断一个数字是否为质数-多语言
  • string接口模拟实现2
  • 18. C++STL 4(vector的使用, 空间增长, 迭代器失效详解)
  • HCIA笔记6--路由基础