【Linux 0.12】80x86保护模式——任务管理
80x86保护模式及其编程
任务管理
任务(Task)是处理器可以分配、调度、执行和挂起的一个工作单元。他可以用于执行程序、任务或进程、操作系统服务、中断或异常处理过程和内核代码。
80x86提供了一种机制,用来保存任务的状态、分派任务执行以及从一个任务切换到另一个任务。当工作在保护模式下,处理器所有运行都在任务中。即使是简单系统也必须至少定义一个任务。更为复杂的系统可以使用处理器的任务管理功能来支持多任务应用。
80x86提供了多任务的硬件支持。任务是一个正在运行的程序,或者是一个等待准备运行的程序。通过中断、异常、跳转或者调用,我们可以执行一个任务。当这些控制转移形式之一和某个描述符表中指定项的内容一起使用时,那么这个描述符就是一类导致新任务开始执行的描述符(??)。描述符表中和任务相关的描述符有两类:任务状态段描述符,任务门。当执行权传给其中一类描述符时,会造成任务切换。
任务的切换很像过程调用,但是会保存更多的处理器状态信息。任务切换会把控制权几乎完全转移到一个新的执行环境,即新任务的执行环境。这种转移操作要求保存处理器中几乎所有寄存器的当前内容,包括标志寄存器EFLAGS和所有段寄存器。与过程不同,任务不可重入。任务切换不会把任何信息压入堆栈,处理器的状态信息都被保存在内存中的称为任务状态段(TSS)的数据结构中。
任务的结构和状态
任务由两部分组成:
- 任务执行空间:代码段,若干数据段,堆栈段(每个特权级都需要各自的堆栈段)
- TSS:指定构成任务执行空间的各个段,位任务状态信息提供存储空间,在多任务环境下为任务之间的链接提供处理方法。
一个任务的使用由其TSS段选择符决定。当一个任务被加载到处理器执行时,该任务的段选择符、基地址、段限长、TSS段描述符属性等会被加载到任务寄存器TR(Task Register)。如果使用了分页机制,页目录表的基地址会加载到CR3中。
当前任务的状态由处理器的以下内容组成:
- 所有通用寄存器和段寄存器
- EFLAGS,EIP,CR3,TR和LDTR
- 段寄存器指定的任务当前执行空间
- I/O 映射位图基地址和I/O位图信息(TSS中)
- 特权级0,1,2的堆栈指针(TSS中)
- 链接到前一个任务的链指针(在TSS中)
任务的执行
软件或处理器可以使用以下方法之一来调度一个任务:
- CALL指令,明确调用一个任务
- JMP指令,明确跳转到一个任务(Linux 内核使用的方式)
- (由处理器)隐式调用一个中断句柄处理任务
- 隐含地调用一个异常句柄处理任务
所有任务调度的方法都会使用一个指向任务门或者任务TSS段的短选择符来确定一个任务。
调度一个任务执行时,当前正在运行任务和任务之间会自动发生任务切换。在任务切换期间,当前运行任务的执行环境(称为任务的状态或者上下文)会被保存到它的TSS中并暂停任务执行。此后新调度任务的上下文会被加载到处理器,并且从加载的EIP指向的指令处开始执行新任务。
如果当前执行任务调用了被调用的新任务,那么调用者的TSS段选择符会保存在被调用者的TSS,从而提供一个返回调用者的链接。(任务不能调用或跳转自己,即不可递归)
作为任务切换操作的一部分,处理器也会切换到另一个LDT,从而允许每个任务对基于LDT的段具有不同逻辑到物理地址的映射。同时,页目录寄存器CR3也会在切换时被重新加载,因此不同任务可以有自己的一套页表。
任务管理数据结构
1. 任务状态段TSS
用于恢复一个任务执行的处理器状态信息保存在称为任务状态段TSS的段中。
TSS的字段可以分为两类:动态字段和静态字段。
动态字段:当任务切换而被挂起时,处理器会自动更新的字段。
- 通用寄存器字段:EDI,ESI,EAX,EBX等等
- 段选择符字段:保存ES,CS等段寄存器的内容
- 指令指针EIP字段
- 先前任务链接(Previous Task Link):含有铅一个任务的段选择符。该字段允许任务通过使用IRET指令返回到前一个任务。
静态字段:该字段在任务被创建时设置,处理器只读取不修改
- LDT段选择符字段
- CR3控制寄存器字段
- 特权级位0,1,2的堆栈指针
- 调试陷阱(Debug Trap)T标志字段
- IO位图基地址字段
2. TSS描述符
TSS描述符只能放在GDT中。
TYPE字段的B用于指明任务是否处于忙状态。
处于忙状态的任务指的是当前正在执行的任务,或者等待执行(被挂起)的任务
3. 任务寄存器TR和任务门描述符
任务寄存器TR存放16bit的段选择符以及当前任务TSS段的整个描述符(不可见部分)。这些信息是从GDT中当前任务的TSS描述符中复制过来的。处理器使用TR的不可见部分来缓冲TSS段的描述符内容。
4. 任务门描述符
任务门描述符提供对一个任务间接,受保护的引用。
任务门描述符可以被存放在GDT、LDT、IDT中。
任务门描述符的TSS选择符字段指向GDT的一个TSS段描述符,其RPL域不使用。门描述符的DPL用于在任务切换时控制对TSS段的访问。当程序通过任务门调用或跳转到另一个任务时,程序的CPL以及指向任务门的门选择符的RPL必须小于或等于任务门描述符的DPL。