📂 操作系统 - Operating System / Chapter II 虚拟化 / Section 1 CPU虚拟化 / 1-2 机制:受限直接执行

在进程间切换

2026-05-09
#OS
  • 进程的切换就是CPU停下手头的进程,转而执行另一个进程

    [!NOTE] Introduction 进程的切换就是CPU停下手头的进程,转而执行另一个进程,但是这其中存在问题

    • 当CPU上有进程正在运行时,OS显然没有运行。那么OS要是想完成进程的调度,它该如何重新获得CPU的控制权
    • 各个进程被调度走或者开始运行时,它们的状态(上下文)如何保存或恢复
  • 操作系统如何重获CPU的控制权

    • 协作方式:等待系统调用(过去的操作系统)
      1. 程序可以通过系统调用(I/O或yeild等)来将控制权交给操作系统,此时操作系统可以控制各个进程运行与否
      2. 程序执行了某些非法操作(例如执行5除以0或者访问非法内存),那么操作系统就会接管CPU做出一些操作来阻止问题(可能会终止违规进程)
      3. 这种方式太被动了,如果遇到一个一直循环还不出错的程序,那操作系统就完全用不了了,这种方式并不是人们想要的
    • 非协作方式:操作系统进行控制
      1. 没有协作的情况下让CPU取得控制权的方式:利用时钟中断
      2. 存在这么一个时钟设备,它是一个硬件设备,可以预设发出时钟中断的周期。它以固定的周期发送中断信号CPU,CPU在执行完正在执行的指令后会立刻收到该信号
      3. 然后CPU与OS会协同保存上下文
      4. 接下来CPU会根据中断号寻找一片叫做断描述符表(IDT) 的内存区域,在其中寻找接下来的处理程序
      5. IDT中,CPU会找到这个时钟中断对应的是时钟中断服务程序(Timer ISR)
      6. 然后CPU就开始由操作系统接管,执行内核级的时钟中断服务程序,这个程序中有许多行动,其中可能包含了调度进程。不过并不是所有的ISR都会引发进程调度,OS会设置一个标志,并在ISR返回前根据标志判断是否进行进程调度
  • 保存和恢复上下文

    • 前置科技树
      • 用户栈与内核栈
        • 一个程序拥有两个栈:
          • 用户栈(User Stack)
            • 位于用户段,用于函数调用、保存局部变量
          • 内核栈(Kernel Stack)
            • 位于内核段,专门在当程序处在内核态时使用(系统调用、中断等)
      • 上下文
        • 上下文是当进程被中断时,这个进程的CPU硬件存储器的状态的完整拷贝
        • 一个进程的上下文只在中断发生时,CPU从用户态陷入内核态后被创建;一直保留到CPU重新回到这个进程时才会被弹出,这里的弹出不是指释放内存,而是这片内存不再有用,之后当中断又发生时,这片内存可以被该进程的新的上下文覆盖
        • 当CPU在内核态执行一个进程时可能会有新的中断发生,此时该进程会再拥有一个新的上下文,原先的上下文仍然保留。在返回到进程时,必须按照FILO的顺序读取上下文
        • 上下文保存了许多当前进程的至关重要的值,包括:
          • 程序计数器(PC):指向下一条要执行的指令地址
          • 程序状态字:包含条件码、中断开关等状态标志
          • 其它通用寄存器,如CS、SS等段寄存器
        • 上下文存储了进程在这一时刻的状态,在将来CPU回到这个进程时,它将可以使这个进程继续此时的状态运行,就像中断从未发生过
      • PCB(Process Control Block)
        • PCB是内核中用于管理和描述一个进程的数据结构
        • PCB在进程被启动时就被创建好了,一直到进程结束才被释放
        • PCB包含了进程的所有信息,如:
          • PID:进程的唯一标识
          • 进程状态:running、sleeping、ready等
          • 调度信息:优先级、调度策略、运行时间等
          • 内存管理信息:页表、指向内存的指针等
          • 文件管理信息:打开的文件、当前的工作目录等
          • 资源信息:占用的各种资源
          • 指向内核栈的指针:是一个内核栈指针或者一个保存了寄存器集合的结构体指针,能够通过这个指针找到内核栈,进而找到上下文
        • PCB可以非常全面地管理和控制进程
    • 保存上下文
      1. CPU受到中断信号前往当前程序的内核栈,CPU自动将当前进程的上下文中的部分寄存器压入内核栈,OS(中断处理程序)接管CPU并将上下文中的剩余通用寄存器压入内核栈
      2. 再然后可能CPU就会去执行时钟中断的ISR了,其中包括调度进程
    • 调度(切换)进程
      1. 如果OS要开始调度进程,那么在执行调度之前,要保存的信息就不止上下文那么少了,而是还需要更新PCB:将内核栈的栈顶指针保存到PCB内
      2. PCB更新完毕后,OS会决定接下来执行什么进程
    • 恢复上下文
      1. OS决定好后,就会从将要执行的进程的PCB中加载它的内核栈的栈顶指针,找到内核栈、上下文,切换当前使用的内核栈。内核代码开始从新的内核栈上弹出寄存器(由汇编switch_to函数完成,是保存上下文的逆过程),恢复这个进程上次被中断时的执行状态。
      2. ISR的最后会有中断返回指令,CPU从内核态返回用户态,执行将要执行的进程