异常控制流

异常:

异常是程序在运行过程中出现的突变,处理器状态的变化称为事件,事件可能和当前指令的执行直接相关,例如发生内存缺页,除零操作等等。

当处理器检测到事件发生时,会通过一张异常表运行相应的异常处理程序。

程序的返回情况有三种:
1、处理程序将控制返回给出错时运行的指令Icur

2、处理程序将控制返回给出错时的下一个指令Inext

3、处理程序终止被中断的程序

异常处理由软件和硬件两部分组成。

零除、缺页等错误有硬件分配异常号,系统调用和外部I/O信号由内核分配异常号。

异常处理程序运行在内核模式下,可以访问所有系统资源。但返回时,如果中断的是用户程序,就会回复为用户模式。

异常分为4类:

1、中断:来自I/O设备的信号,总是返回下一条指令,在用户看来没发生过一样

2、陷阱:故意的异常,为了中断当前程序进行其他服务例如read,fork等。

3、故障:潜在可恢复错误,视修复情况,可能会返回当前指令。

4、终止:不可恢复错误,不会返回,通常是一些不可恢复的硬件错误。

 

syscall是系统调用指令,一般在c里面做了封装,带上合适的参数之后封装在系统级函数中。

用户模式和内核模式:由模式位的状态决定。

用户模式:不允许执行特权指令,停止处理器、改变模式位、发起I/O操作等,也不允许直接引用内核区中的代码和数据,否则会引起保护故障。所以必须要通过系统调用借口来调用。

linux提供了proc文件系统,为用户模式进程提供访问内核数据结构内容的功能,可以通过这个文件系统找出一般的系统属性。

上下文切换:两个进程间切换任务,内核会保存上一个进程的状态,包括一系列寄存器和内核栈等等的信息。等待另一个任务结束后会根据之前保存的信息恢复新进程。

通常操作系统把虚拟地址空间划分为用户空间和内核空间,例如x86平台的Linux系统虚拟地址空间是0x00000000~0xffffffff,前3GB(0x00000000~0xbfffffff)是用户空间,后1GB(0xc0000000~0xffffffff)是内核空间。用户程序加载到用户空间,在用户模式下执行,不能访问内核中的数据,也不能跳转到内核代码中执行。这样可以保护内核,如果一个进程访问了非法地址,顶多这一个进程崩溃,而不会影响到内核和整个系统的稳定性。CPU在产生中断或异常时不仅会跳转到中断或异常服务程序,还会自动切换模式,从用户模式切换到特权模式,因此从中断或异常服务程序可以跳转到内核代码中执行。事实上,整个内核就是由各种中断和异常处理程序组成的。总结一下:在正常情况下处理器在用户模式执行用户程序,在中断或异常情况下处理器切换到特权模式执行内核程序,处理完中断或异常之后再返回用户模式继续执行用户程序。

段错误我们已经遇到过很多次了,它是这样产生的:

  1. 用户程序要访问的一个VA,经MMU检查无权访问。

  2. MMU产生一个异常,CPU从用户模式切换到特权模式,跳转到内核代码中执行异常服务程序。

  3. 内核把这个异常解释为段错误,把引发异常的进程终止掉。

<think>我们正在讨论程序控制指令的分类。用户询问是否可以分为正常控制流异常控制流。 根据计算机系统的一般概念: - 正常控制流(Normal Control Flow)是指程序按照指令顺序执行,或者通过跳转、调用、循环等指令改变执行流程,但这些改变是程序开发者有意设计的。 - 异常控制流(Exceptional Control Flow)是指由于某些异常事件(如硬件中断、系统调用、程序错误等)导致的非预期控制流转移。 在指令集架构层面,程序控制指令通常包括: 1. 跳转指令(JMP) 2. 条件分支指令(Jcc) 3. 子程序调用和返回(CALL/RET) 4. 循环控制指令(LOOP等) 这些都属于正常控制流指令,因为它们是由程序显式安排的流程改变。 而异常控制流通常由以下情况触发: - 硬件中断(如时钟中断、I/O中断) - 处理器异常(如除零异常、缺页异常) - 系统调用(通过软中断或专用指令,如x86的INT/SYSCALL) 在高级语言中,异常处理(如try-catch)也是异常控制流的一种表现,但在机器指令层面,它通常通过跳转指令和特定的异常处理机制实现。 因此,我们可以将程序控制指令分为两类: 1. 正常控制流指令:包括跳转、分支、调用、返回、循环等。 2. 异常控制流指令:包括中断指令(如INT)、系统调用指令(如SYSCALL/SYSENTER)以及处理器内部用于异常处理的机制(这些通常不是显式的指令,而是由硬件触发)。 注意:异常控制流指令通常不是由程序直接调用(除了系统调用),而是由硬件或操作系统在特定条件下触发。 参考用户提供的引用: 引用[1]和[2]讨论了Java中的异常处理,将异常分为受检异常和非受检异常(RuntimeException),这属于高级语言层面的异常控制流。 引用[3]和[4]则提到了异常捕获和处理,也属于高级语言层面。 在指令集层面,异常控制流通常通过中断和异常处理机制实现,而程序控制指令主要处理正常控制流。 因此,回答用户的问题:是的,程序控制指令可以分为正常控制流指令和异常控制流指令。 下面我们详细说明: ### 一、正常控制流指令 这类指令是程序主动改变控制流的指令,包括: 1. 跳转指令(JMP) 2. 条件分支指令(JE, JNE, JG等) 3. 子程序调用和返回(CALL/RET) 4. 循环指令(LOOP, LOOPZ等) 这些指令的特点是由程序显式使用,控制流转移的目标地址在指令中指定或由寄存器给出。 ### 二、异常控制流指令 这类指令用于处理非预期的或由外部事件触发的控制流转移,包括: 1. 中断指令(如x86的INT n):主动触发软件中断,通常用于系统调用。 2. 系统调用指令(如x86的SYSCALL/SYSENTER):专门用于快速系统调用。 3. 中断返回指令(如IRET):用于从中断处理程序返回。 4. 处理器异常:由硬件自动触发,例如除零异常(对应x86的DIV指令出错时)或页错误,这些不是指令,而是事件。 注意:异常控制流指令的执行通常伴随着处理器状态的保存和恢复(如压栈保存现场),以及控制权转移到操作系统内核。 在高级语言中,异常处理机制(如try-catch)在底层通常通过正常控制流指令(跳转)和操作系统/运行时的异常处理机制(异常控制流)共同实现。 因此,我们可以这样总结: 程序控制指令在指令集层面可以分为: - **正常控制流指令**:程序主动控制的跳转、分支、调用、返回、循环等。 - **异常控制流指令**:用于响应外部事件或错误的指令(如INT、SYSCALL、IRET),以及由硬件自动触发的异常处理机制。 需要说明的是,硬件自动触发的异常处理机制并不是一条指令,而是一个过程,但它的效果相当于控制流的改变。 下面我们根据用户提供的引用,看看高级语言层面的异常控制流与指令集层面的关系: 引用[1]中展示了Java的FileInputStream类,其中read方法抛出了IOException(受检异常)。在底层,当发生I/O错误时,操作系统会产生一个中断或异常信号,然后由JVM捕获并转换为Java异常抛出。 引用[2]提到,受检异常用于期望调用者能够恢复的情况,而非受检异常(RuntimeException)通常表示程序错误。在底层,非受检异常可能由硬件异常(如空指针访问)触发,而受检异常则可能由系统调用错误(如文件不存在)触发。 引用[3]和[4]则说明了异常捕获的语法和常见异常类型,这些异常在底层都对应着异常控制流的处理。 因此,从整个计算机系统的角度,控制流可以分为正常和异常,而指令集也提供了相应的指令支持。 最后,我们生成相关问题:</think>### 程序控制指令的分类:正常控制流异常控制流 程序控制指令可分为**正常控制流**和**异常控制流**两类,二者在触发机制、处理逻辑和设计目标上存在本质区别。以下是具体分析: --- #### 一、正常控制流指令 通过**显式指令**主动改变程序执行顺序,是开发者预期的流程控制。 1. **核心类型**: - 跳转指令(`JMP`/`Jcc`) - 子程序调用/返回(`CALL`/`RET`) - 循环控制(`LOOP`) 2. **特点**: - **主动触发**:由程序显式调用(如`CALL SUB_ROUTINE`)。 - **可预测性**:流程转移目标明确(如跳转至标号`LABEL`)。 - **堆栈管理**:依赖堆栈保存返回地址(`CALL`压栈,`RET`弹栈)[^1]。 --- #### 二、异常控制流指令 由**非预期事件**触发的控制流转移,用于处理错误或外部中断。 1. **触发条件**: - **硬件异常**:除零错误、缺页中断等(如`#DE`除零异常)。 - **软件异常**:显式抛出异常(如`throw new IOException()`)[^1]。 - **外部中断**:时钟中断、I/O设备信号等。 2. **处理机制**: - **中断向量表**:通过预定义入口跳转至处理程序。 - **上下文保存**:自动保存寄存器状态(如`EFLAGS`、`CS:IP`)。 - **异常分类**: - **受检异常**(Checked):需显式处理(如Java的`IOException`)[^2]。 - **非受检异常**(Unchecked):逻辑错误(如`NullPointerException`)[^4]。 3. **示例**: ```java // Java异常控制流(受检异常) public int read() throws IOException { return read0(); // 可能触发IOException[^1] } ``` --- ### 核心区别 | **特性** | 正常控制流 | 异常控制流 | |------------------|---------------------------|---------------------------| | **触发方式** | 显式指令(如`CALL`) | 事件驱动(错误/中断) | | **目标地址** | 固定标号或地址 | 通过中断向量表动态跳转 | | **恢复机制** | 通过`RET`返回原流程 | 需显式恢复上下文或终止程序 | | **设计目标** | 实现分支、循环、模块化 | 容错处理或响应外部事件 | > **关键洞察**: > - 正常控制流是**程序主动设计**的流程(如函数调用);异常控制流是**被动响应**机制(如错误处理)[^2][^4]。 > - 异常控制流通常需要操作系统/运行时环境支持(如中断处理程序)[^3]。 ---
评论
成就一亿技术人!
拼手气红包6.0元
还能输入1000个字符
 
红包 添加红包
表情包 插入表情
 条评论被折叠 查看
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值