csapp 第八章 异常控制流
异常处理
异常的类别
异常(Exception)都是运行时的。编译时产生的不是异常,而是错误(Error)。
异常分为四类:1,中断。2、陷阱。3、故障、4、终止。
异步异常是用外部的设备,输入输出设备中的事件产生的。同步异常是执行一条指令的产物。
1、中断
中断是异步发生的,是来自外部设备的结果。(硬件中断不是由任何一条专门的指令造成的)。
硬件中断的异常处理程序被称为中断处理程序。
这个中断,举个例子,比如我们生活中,家庭中有个电器的总闸,总闸里面有保险丝,当电流过大时,会使保险丝熔断,发生跳闸,这个时候,传输到我们家里面的电流,就中断了,需要我们排除异常之后,才能把闸拉上去。
2、陷阱和系统调用
陷阱是有意的异常,是执行一条指令的结果。属于同步异常。陷阱的一个重要用途是在用户程序和内核提供一个像过程一样的接口,叫做系统调用。
用户程序(就是如我们的鼠标点击的运行的程序),需要经常向内核请求服务,比如读取一个文件,加载一个新的程序,或者终止当前的程序。为了允许这些请求,处理器提供了一条特殊的指令syscall .执行sycall指令会导致一个到异常处理程序的陷阱,从而调用适当的内核程序。
系统调用和普通函数调用是一样的,但是它们的实现有很大的不同,普通函数运行在用户模式中,而系统调用运行在内核模式中。
3、 故障
由错误情况引起,它可能被故障处理程序修正。
4、终止
发生不可恢复的致命错误时,会发生终止异常,属于同步异常。通常是一些硬件错误
进程
逻辑控制流
比如好几个程序运行,A程序运行一会儿,然后B程序运行一会儿,然后再C程序运行一会儿,这样交替运行,直到全部程序运行完.它提供了一个假象,好像我们的程序单独的占用处理器.
关键点就在于进程是轮流使用处理器的,每个进程执行它的流的一部分,然后被”抢占”,暂时挂起,然后轮到其他的进程
并发流
一个逻辑流的执行在时间上与另一个流重叠,称为并发流 ,这两个流被称为并发的运行.
多个流并发的执行的现象被称为并发
一个进程和其他进程轮流运行被称为多任务
一个进程执行它的控制流的一部分的每一段时间叫做时间片 ,因而多任务也叫做时间分片
用户模式和内核模式
处理器通过一个控制寄存器中的一个模式位来提供这种功能,当设置了模式位时,进程运行就运行在了内核模式中.这时,该进程就可以执行指令集的任何指令,并且可以访问系统中的任何位置.因此内核模式可以被称为超级用户模式.
在用户模式下,进程不允许执行特权指令,和直接引用地址空间中内核区的代码和数据,这样的任何尝试都会导致致命的保护故障.用户程序必须通过系统调用接口间接的访问内核代码和数据.
运行应用程序代码的进程初始时是在用户模式中的,进程从用户模式变为内核模式的唯一方法是通过诸如中端,故障或者陷入系统调用的异常.当异常发生时控制传递到异常处理程序,处理器将其从用户模式变成内核模式.
当程序返回到应用程序代码时,处理器就把模式从内核模式切换回用户模式.
上下文切换
什么是上下文切换呢?上下文切换就是内核重新启动一个暂时休眠的进程所需的状态,它由一些对象的值组成,包括通用目的寄存器,浮点寄存器,程序计数器,用户栈,状态寄存器,各种内核数据结构,比如进程表,页表,等等
进程在执行时,内核可以决定是否让当前进程运行,并让其他休眠的进程开始运行。这个决策就叫做调度 ,由内核中调度器代码处理。当内核选择一个新的进程进行运行的时候,我们就称其为内核调度了这个进程,在这个过程中内核使用上下文切换机制来控制两个进程的休眠运行。
如果系统调用因为等待一个事件而发生阻塞,那么内核可以让当前进程休眠,然后切换到另一个进程。可以使用sleep系统调用,显式的请求让调用程序进行休眠。
如图就是两个进程进行切换的表示。
![image-20230219100641275](/../csapp 第八章 异常控制流/image-20230219100641275.png)
进程控制
1获取进程ID
每一个进程都有一个唯一正数的进程ID(PID)
2、创建和终止进程
我们可以认为进程总是存在三种状态:
- 运行。
- 停止。进程的执行被挂起(休眠)
- 终止。进程永远的停止,不再执行。1、收到终止信号。2、从主程序返回。3、调用exit函数。
父进程可以通过调用fork函数来创建一个子进程(也就是在进程中再创建一个进程)
fork函数创建进程的时候 的一些特点:
调用一次,返回两次。
并发进行。
相同但是独立的地址空间。它们进程的地址空间是相同的,但是因为父进程和子进程是独立的进程,它们有着自己的私有空间。
共享文件。因为子进程会继承父进程大部分东西。相似但是有区别。
3、进程休眠
一般的,我们运用sleep函数将一个进程挂起指定的一段时间
4、回收子进程
当一个进程由于某种原因终止的时候,内核并不会立即将它从系统中清除,而是保持在一种已终止的状态中,直到被父进程回收。一个终止了但是还未被回收的进程被称为僵死进程,虽然他们没有运行,但是它们仍然会消耗系统的内存资源。一般我们用waitpid函数来等待它的子进程终止或者停止。
信号
信号的作用就是通知进程系统中发生的某种类型的事件。每种信号类型都对应着某种系统事件,当发生了一个异常,就会通知用户进程。
信号表