信息安全系统设计基础第十一周学习总结
第八章 异常控制流
8.1异常
异常是异常控制流的一种形式,它一部分是由硬件实现的,一部分是由操作系统实现的。有一部分是由硬件实现的,所以具体细节将随系统的不同而有所不同。
异常的剖析:
当异常处理程序完成处理后,根据引起异常的事件的类型,会发生以下三种情况中的一种:
*处理程序将控制返回给当前指令Icurr,即当事件发生时正在执行的指令。
*处理程序将控制返回给Inext,即如果没有发生异常将会执行的下一条指令。
*处理程序终止被中断的程序。
异常的类别——中断、陷阱、故障和终止
中断处理:异步是指硬件中断不是由任何一条指令造成的,而是由外部I/O设备的事件造成的。
陷阱和系统调用:系统调用是一些封装好的函数,内部通过指令int n实现。
陷阱最重要的用途是提供系统调用。系统调用运行在内核模式中,并且可以访问内核中的栈。
系统调用的参数是通过通用寄存器而不是栈来传递的,如,%eax存储系统调用号,%ebx,%ecx,%edx,%esi,%edi,%ebp最多存储六个参数,%esp不能用,因为进入内核模式后,会覆盖掉它。
故障
一个经典的的故障示例是缺页异常,当指令引用一个虚拟地址,而该虚拟地址相对应的物理页面不在存储器中,因此必须从磁盘中取出时,就会发生故障。
终止
终止是不可恢复的致命错误造成的结果,通常是一些硬件错误,比如DRAM或者SRAM位被损坏时发生的奇偶错误。终止处理程序从不将控制返回给应用程序。处理程序将控制返回给一个abort例程,该例程会终止这个应用程序。
8.2进程
- 异常是允许操作系统提供进程 (process) 的概念所需要的基本构造块。
系统中的每个程序都是运行在某个进程的上 下文 (context) 中的。上下文是由程序正确运行所需的状态组成的。这个状态包括存放在存储器 中的程序的代码和数据,它的栈、通用目的寄存器的内容、程序计数器、环境变量以及打开文件 描述符的集合。
2.并发流487
*并发流:并发流一个逻辑流的执行在时间上与另一个流重叠,叫做并行流
*并发:多个流并发执行的一般现象称为并发。
*多任务:多个进程并发叫做多任务。
*并行:并发流在不同的cpu或计算机上,叫做并行。
3.用户模式和内核模式488
*运行应用程序代码的进程初始时是在用户模式中的。进程从用户模式变为内核模式的唯一方法是通过异常。
*linux提供了/proc文件系统,它允许用户模式进程访问内核数据结构的内容。
8.3系统调用错误处理
1.当Unix系统级函数遇到错误时,它们典型地会返回―1,并设置全局整数变量errno来表示什么出错了。程序员应该总是检查错误,但是不幸的是,许多人都忽略了错误检查,因为它使代码变得臃肿,而且难以读懂。
2.通过使用错误处理包装函数,我们可以更进一步地简化我们的代码。对于一个给定的基本函数foo,我们定义一个具有相同参数的包装函数Foo,但是第一个字母大写了。包装函数调用基本函数,检查错误,如果有任何问题就终止。
8.4进程控制
Unix 信号,它允许进程中断其他进程。一个信号就是一条小消息,它通知进程系统中发生了一个某种类型的事件。
1.进程的三种状态——运行、停止和终止。
进程会因为三种原因终止进程:收到信号,该信号默认终止进程;从主程序返回;调用exit函数。
2.回收子进程495
回收:当一个进程终止时,内核并不立即把它从系统中清除。相反,进程被保持在一种已终止的状态中,直到被它的父进程回收。
僵死进程:一个终止了但是还未被回收的进程称为僵死进程。
回收子进程的两种方法:1,内核的init进程 2,父进程waitpid函数
1)如果父进程没有回收它的僵死子进程就终止了,那么内核就会安排init进城来回收它们。init进程的PID为1,并且是在系统初始化时创建的。
2)一个进程可以通过调用waitpid函数来等待它的子进程终止或停止。
waitpid函数有点复杂,默认地(当options=0时),waitpid挂起调用进程的执行,知道它的等待集合中的一个子进程终止。
3.加载并运行程序500
1)execve函数加载并运行可执行目标文件filename,且带参数列表argv和环境变量列表envp。只有当出现错误时,例如找不到filename,execve才会返回到调用程序。所以,与fork一次调用返回两次不同,execve调用一次并从不返回。
2)参数中每个指针都指向一个参数串。按照惯例,argv[0]是可执行目标文件的名字。环境变量的列表是由一个类似的数据结构表示的。envp变量指向一个以null结尾的指针数组,其中每个指针指向个环境变量串,其中每个串都是形如“NAME=VALUE”的名字一值对。
8.5信号
传送一个信号到目的进程是由两个不同步骤组成的 :
发送信号。内核通过更新目的进程上下文中的某个状态,发送(递送)一个信号给目的进程。发送信号可以有如下两个原因:1)内核检测到一个系统事件,比如被零除错误或者子进程终止。 2) 一个进程调用了 kill 函数,显式地要求内核发送一个信号给目的进程。一个进程可以发送信号给它自己。
接收信号。当目的进程被内核强迫以某种方式对信号的发送做出反应时,目的进程就接收了信号。进程可以忽略这个信号,终止或者通过执行一个称为信 号处理程序 (signal handler) 的用户层函数捕获这个信号
一个只发出而没有被接收的信号叫做待处理信号 (pending signal)。 在任何时刻,一种类型至多只会有一个待处理信号。
一个进程可以有 选择性地阻塞接收某种信号。当一 种信号被阻塞时,它仍可以被发送, 但是产生的待处理信号不会被接收, 直到进程取消对这种信号的阻塞。
一个待处理信号最多只能被接收一次。