C++--问题24--进程的上下文切换
1.进程是什么?
我们编写的代码只是一个存储在硬盘的静态文件,通过编译后就会生成二进制可执行文件,当我们运行这个可执行文件后,它会被装载到内存中,接着 CPU 会执行程序中的每一条指令,那么这个运行中的程序,就被称为进程。
进程在不同的操作系统中有些称为process,有些称为task。操作系统中进程数据结构包含了很多元素,往往用链表连接。
进程间的状态转换图:
还有一个状态叫挂起状态,它表示进程没有占有物理内存空间。这跟阻塞状态是不一样,阻塞状态是等待某个事件的返回。
由于虚拟内存管理原因,进程的所使用的空间可能并没有映射到物理内存,而是在硬盘上,这时进程就会出现挂起状态,另外调用 sleep 也会被挂起。
2.PCB是什么?
在操作系统中,是用进程控制块(process control block,PCB)数据结构来描述进程的。
PCB 是进程存在的唯一标识,这意味着一个进程的存在,必然会有一个 PCB,如果进程消失了,那么 PCB 也会随之消失。
PCB 具体包含信息:
(1)进程描述信息
进程标识符:标识各个进程,每个进程都有一个并且唯一的标识符;
用户标识符:进程归属的用户,用户标识符主要为共享和保护服务;
(2)进程控制和管理信息
进程当前状态,如 new、ready、running、waiting 或 blocked 等;
进程优先级:进程抢占 CPU 时的优先级;
(3)资源分配清单
有关内存地址空间或虚拟地址空间的信息,所打开文件的列表和所使用的 I/O 设备信息。
(4)CPU 相关信息
CPU 中各个寄存器的值,当进程被切换时,CPU 的状态信息都会被保存在相应的 PCB 中,以便进程重新执行时,能从断点处继续执行。
3.进程上下文切换
各个进程之间是共享 CPU 资源的,在不同的时候进程之间需要切换,让不同的进程可以在 CPU 执行,那么这个一个进程切换到另一个进程运行,称为进程的上下文切换。
CPU 寄存器和程序计数器是 CPU 在运行任何任务前,所必须依赖的环境,这些环境就叫做 CPU 上下文。
CPU 寄存器是 CPU 内部一个容量小,但是速度极快的内存(缓存)。
程序计数器是用来存储 CPU 正在执行的指令位置、或者即将执行的下一条指令位置。
CPU 上下文切换本质就是:先把前一个任务的 CPU 上下文(CPU 寄存器和程序计数器)保存起来,然后加载新任务的上下文到这些寄存器和程序计数器,最后再跳转到程序计数器所指的新位置,运行新任务。
4.进程的上下文切换到底是切换什么呢?
进程是由内核管理和调度的,所以进程的切换只能发生在内核态。
进程的上下文切换不仅包含了虚拟内存、栈、全局变量等用户空间的资源,还包括了内核堆栈、寄存器等内核空间的资源。
过程:把交换的信息保存在进程的 PCB,当要运行进程2的时候,我们需要从进程2的 PCB 取出上下文,然后恢复到 CPU 中,这样使得这个进程可以继续执行。
5.发生进程上下文切换有哪些场景?
(1)时间片耗尽:为了保证所有进程可以得到公平调度,CPU 时间被划分为一段段的时间片,这些时间片再被轮流分配给各个进程。这样,当某个进程的时间片耗尽了,就会被系统挂起,切换到其它正在等待 CPU 的进程运行;
(2)系统资源不足:进程在系统资源不足(比如内存不足)时,要等到资源满足后才可以运行,这个时候进程也会被挂起,并由系统调度其他进程运行;
(3)睡眠函数 sleep :当进程通过睡眠函数 sleep 这样的方法将自己主动挂起时,自然也会重新调度;
(4)高优先级进程进来:当有优先级更高的进程运行时,为了保证高优先级进程的运行,当前进程会被挂起,由高优先级进程来运行;
(5)硬件中断:发生硬件中断时,CPU 上的进程会被中断挂起,转而执行内核中的中断服务程序。