天天看点

操作系统真象还原第十一章11.1 为什么要有任务状态段 TSS11.3 实现用户进程

11.1 为什么要有任务状态段 TSS

11.1.1 多任务的起源

TSS 是 Task State Segment 的缩写,即任务状态段。

硬件厂商提供的多任务硬件解决方案主要是 LDT 和 TSS。

11.1.3 TSS 的作用

Intel 的建议是给每个任务关联一个任务状态段,这就是 TSS,用它来表示任务。

TSS 是由程序员“提供”的,由 CPU 来维护。

CPU 中有一个专门存储 TSS 信息的寄存器,这就是 TR 寄存器,它始终指向当前正在运行的任务。

TSS 和其它段一样,本质上是一片存储数据的内存区域,Intel 打算用这片内存区域保存任务的最新状态。使用 TSS 描述符来“描述” TSS。

操作系统真象还原第十一章11.1 为什么要有任务状态段 TSS11.3 实现用户进程

TSS 描述符属于系统段描述符。

操作系统真象还原第十一章11.1 为什么要有任务状态段 TSS11.3 实现用户进程

TSS 的主要作用就是保存任务的快照,也就是 CPU 执行该任务时,寄存器当时的瞬时值。

除了从中断和调用门返回外,CPU 不允许从高特权级转向低特权级。另外,CPU 在不同特权级下用不同的栈。

Linux 只用到了 0 特权级和 3 特权级,因此只设置 SS0 和 esp0 的值就够了。

TR 寄存器存储 TSS 的起始地址及偏移大小。

操作系统真象还原第十一章11.1 为什么要有任务状态段 TSS11.3 实现用户进程

TSS 必须要在 GDT 中注册,因此 TSS 是通过选择子来访问的,将 TSS 加载到寄存器 TR 的指令时 ltr:

ltr <16位通用寄存器>/<16位内存单元>
           

11.1.5 现代操作系统采用的任务切换方式

有一件工作必须且只能用 TSS 来完成,就是 CPU 向更高特权级转移时所使用的栈地址,需要提前在 TSS 中写入。

导致转移到更高特权级的一种情况是在用户模式下发生中断,CPU 会由低特权级进入高特权级,这会发生堆栈的切换。当一个中断发生在用户模式(特权级3),处理器从当前 TSS 的 SS0 和 esp0 成员中获取用于处理中断的堆栈。因此,我们必须创建一个 TSS,并且至少初始化 TSS 中的这些字段。

Linux 为每个 CPU 创建一个 TSS,在各个 CPU 上的所有任务共享同一个 TSS。在进程切换时,只需要把 TSS 中的 SS0 及 esp0 更新为新任务的内核栈的段地址及栈指针。

Linux 在 TSS 中只初始化了 SS0、esp0 和 I/O 位图字段。

和修改 TSS 中的内容所带来的开销相比,在 TR 中加载 TSS 的开销要大很多。

11.3 实现用户进程

操作系统真象还原第十一章11.1 为什么要有任务状态段 TSS11.3 实现用户进程

进程与内核线程最大的区别是进程有单独的 4GB 空间,这指的是虚拟地址。

11.3.5 用户进程创建的流程

操作系统真象还原第十一章11.1 为什么要有任务状态段 TSS11.3 实现用户进程

11.3.8 实现用户进程----下

操作系统启动后,其在物理内存中的位置是固定的,不会再变动。

操作系统只有一套页表,它们也是固定的。

操作系统真象还原第十一章11.1 为什么要有任务状态段 TSS11.3 实现用户进程

把用户进程页目录表中的第 768 ~ 1023 个页目录项用内核页目录表的第 768 ~ 1023 个页目录项代替,就能让用户进程的高 1GB 空间指向内核。