2018-2019-1 20165228 《信息安全系统设计基础》第七周学习总结
教材学习内容总结
第八章 异常控制流(Exception Control Flow,ECF)
异常控制流发生在系统的各个层次
- 理解ECF将帮助理解重要的系统概念
- 理解ECF将帮助理解应用程序如何与操作系统交互
- 理解ECF帮助编写有趣的新应用程序
- 理解ECF帮助理解并发
异常
- 异常是异常控制流的一种形式,它一部分由硬件实现,一部分由操作系统实现。
- 异常(exception)就是控制流中的突变,用来响应处理器状态的某种变化。
- 任何情况下,当处理器检测到有事件发生时,它会通过一张叫做异常表(exception tabled)的跳转表,进行一个简介过程调用(异常),到一个专门设计用来处理这类事件的操作系统子程序(异常处理程序(exception handler))。当异常处理子程序完成处理后,根据引起异常的事件的类型,会发生以下3种情况之一:
- 处理程序将控制返回给当前指令Icurr,即当事件发生时正在执行的指令。
- 处理程序将控制返回给Inext,如果没有异常将会执行的下一条指令。
- 处理程序终止被中断的程序。
异常处理
- 在系统启动时,操作系统分配和初始化一张称为异常表的跳转表,使得表目k包含异常k的处理程序的地址。
- 在运行时,处理器检测到发生了一个事件,并且确定了相应的异常号k。随后处理器触发异常,方法是执行间接过程调用,通过异常表的表目k,转到相应的处理程序。
异常的类别
异常分为四类:
- 中断
- 陷阱
- 故障
- 终止
进程
- 异常是允许操作系统提供进程的概念的基本构造快,进程是计算机科学中最深刻,最成功的概念之一
- 进程经典定义:一个执行中的程序实例,系统中每个程序都是运行某个进程的上下文中的,其中上下文是由程序正确运行所需的状态组成。包括存放在内存中的程序的代码和数据,它的栈、通用目的寄存器的内容、程序计数器、环境变量以及打开文件描述符的集合。
逻辑控制流
- PC值的序列叫做逻辑控制流,或者简称逻辑流
并发流
- 逻辑流有许多不同的形式。 异常处理程序,进程,信号处理程序,线程和Java进程都是逻辑流的例子
- 并发流就是一个逻辑流的执行在时间上与另一个流重叠,这两个流并发运行。
- 多个流并发地执行的一般现象称为并发。
- 一个进程执行它的控制流的一部分的每一时间段叫做时间片。所以多任务也成为时间分片。
私有地址空间
- 进程为每个程序提供一种独占使用系统地址空间的假象。
用户模式和内核模式
- 处理器通常使用某个控制寄存器的中的一个模式位来提供限制应用执行的指令和访问地址空间范围的机制。
- 设置模式位,运行在内核模式。即,超级用户模式,可执行任何指令,可访问任何文件。
- 没有设置模式位,运行在用户模式,不允许执行特权指令,也不允许用户模式中的进程直接引用地址空间中内核区内的代码和数据
上下文切换
- 操作系统内核使用一种称为上下文切换的 较高层次 的异常控制流来实现多任务。它建立在较低层异常机制之上的。
- 内核为每一个进程维持一个上下文,即内核重新启动一个被抢占的进程所需的状态。由通用目的寄存器、浮点寄存器、程序计数器等的值和各种内核数据结构组成。
引发上下文切换: - 内核代表用户执行系统调用
- 中断
获取进程ID
#include<sys/types.h>
#include<unistd.h>
pid_t getpid(void);
pid_t getppid(void);
- PID是每个进程唯一的正数。getpid()返回调用进程的PID,getppid()返回它的父进程的PID。
返回一个类型pid_t的值,在Linux系统下在type.h被定义为int
创建和终止进程
进程的三种状态:
- 运行:进程要么在CPU中执行,要么等待执行,最终被内核调度。
- 停止:进程的执行被挂起,且不会被调度。
- 终止:进程永远停止
创建子进程
#include<sys/types.h>
#include<unistd.h>
pid_t fork(void);
返回:子进程返回0,父进程返回子进程的PID,如果出错,返回-1;
- 子进程得到与父进程用户级虚拟地址空间相同的(但是独立的)一份拷贝。
包括文本,数据和bss段,堆以及用户栈。子进程还获得与父进程任何打开文件描述符相同的拷贝。 - 意味着当父进程调用fork时,子进程可以读写父进程中打开的任何文件。
父进程和新创建的子进程之间最大的区别在于有不同的PID。
回收子进程
#include<sys/types.h>
#include<sys/wait.h>
pid_t waitpid(pid_t pid ,int *status, int options);
返回:如果成功,则为子进程的PID,如果WNOHANG,则为0,如果其他错误,则为-1.
- 当一个进程由于某种原因终止时,内核并不是立即把它从系统中清除。相反,进程被保持在一种已终结的状态,知道被它的父进程 回收(reap)。
- 一个进程可以通过调用waitpid函数来等待它的子进程终止或停止
教材学习中的问题和解决过程
- 问题1:如何使用非本地跳转来规避正常的调用/返回栈规则。
- 解决方法: 非本地跳转通过setjmp和longjmp函数来提供。