多任务
是操作系统实现的必要功能,多任务部分负责创建/销毁/调度进程 or 线程
无论是宏内核还是微内核,其内核都必须具备多任务调度的机制
系统进程
是运行在R0
特权级的进程,一般这类进程为 IDLE 进程,系统服务进程,拥有 PC 的最高操作权限
IDLE 进程
是操作系统第一个创建的进程,唯一一个不通过fork()
函数复制得来的进程,其 PID 为0
该进程的调度优先级为最低,一般在调度队列为空时调度该进程
操作系统的初始化等工作由该进程完成 (在多核中由 CPU0 的 IDLE 进程完成,且有几个 CPU 核心就有几个 IDLE 进程)
在操作系统内核初始化完成后该进程并不会销毁,而是循环执行hlt
以降低 CPU 功耗
用户进程
运行在 R3
特权级的进程,一般这类进程为应用程序的进程,只能访问特定内存区域且无法执行特权级指令 (如hlt``sti
lgdt
等)
- 在 x86 平台下,CPU 无法从
R3
特权级直接切换到R0
, 同时R0
也无法直接切换至R3
, 所以在 x86 中唯一从R0
切换至R3
的方式是使用iret
指令跳转 - 涉及特权级切换时,内核必须配置 TSS(Task Statu Segments : 任务状态段), 该结构是
GDT
的一个段描述符 - 每个用户进程会在内核有一块单独的栈,该栈用于用户进程系统调用时候存储
R0
特权级执行时产生的各种数据
在 CP_Kernel 内核中,用户进程在刚创建时是 R0 特权级,这时候内核会往该进程的栈中插入一个名为
switch_to_user_mode
的函数并传入真正的用户程序入口地址switch_to_user_mode
函数负责初始化进入R3
前各种寄存器的值
最后使用iret
指令跳转到用户程序入口地址,这个时候就切换至R3
特权级了
TSS
任务状态段,负责存储一个任务的当前 CPU 状态,其包含了 CPU 所有的寄存器 (控制寄存器以及 GDTR IDTR 除外). 是旧版 x86 平台用于任务切换的一个数据结构。
在现代操作系统中并不会使用该数据结构去进行任务调度,因为 PCB(Process Control Block : 进程控制块) 取代了它。 PCB 相比 TSS 拥有更快的任务切换速度,且可以自定义多种进程私有的数据结构 (如 PID TTY 设备映射 调度时间片计数等)。
但这并不代表不需要配置 TSS, TSS 的作用只是缩减到切换内核栈地址的作用
任务调度
任务调度有很多方式,内核会使用合理的方式分配给这些任务一定的 CPU 时间片,一旦过了该任务的 CPU 时间片就会触发该任务调度。
一个好的任务调度器可以大幅度提高应用程序的运行速度,提高硬件资源的利用效率
进程切换过程中,需要切换的寄存器可以参考 TSS 的结构。
补充
进程间的资源隔离
因为不同的进程之间页目录不同,拥有不同的内存布局,不同进程间相同的线性地址指向的是不同的物理地址
因此该地址获取的数据也不同线程与进程的区别
所以线程之间的资源可以共享,而进程因为切换了页表 (内存布局被切换), 所以资源不共享