任务管理

     任务(TASK)是处理器可以分配,调度,执行和挂起的一个工作单元。它可用于执行任务或进程、操作系统服务、中断或异常处理过的和内核代码。80x86提供了一种机制,这种机制可用来保存任务的状态、分派任务执行以及从一个任务切换到另一个任务。当工作在保护模式下,处理器所有运行都在任务中。即使是简单系统也必须至少定义一个任务。更为复杂的系统可以使用处理器的任务管理功能来支持多任务应用。

      通过中断、异常、跳转或调用,我们可以执行一个任务。当这些控制转移形式之一和某个描述符表中指定项的内容一起使用时,那么这个描述符就是一类导致新任务开始执行的描述符。描述符表中与任务相关的描述符有两类:任务状态段描述符和任务门。当执行权传给这任何一类描述符时,都会造成任务切换。

      任务切换很像过程调用,但会保存更多的处理器状态信息。任何切换会把控制权完全转移到一个新的执行环境,即新任务的执行环境。这种转移操作要求保存处理器中几乎所有寄存器的当前内容,包含标志寄存器EFLAGS和所有段寄存器。与过程不同,任务不可重入。任务切换不会把任何信息压入堆栈中,处理器的状态信息都被保存在内存中称为任务状态段的数据结构中。

任务的结构和状态

      一个任务由两部分构成:任务执行空间和TSS。任务执行空间包括代码段、堆栈段和一个或多个数据段。如果操作系统使用了处理器的特权级保护机制,那么任务执行空间就需要为每个特权级提供一个独立的堆栈空间。TSS制定了构成任务执行空间的各个段,并且为任务状态信息提供了存储空间。在多任务环境中,TSS也为任务之间的链接提供了处理方法。

      一个任务的使用由指向其TSS的段选择符来指定。当一个任务被加载进处理器中执行时,那么该任务的段选择符、基地址、段限长以及TSS段描述符属性就会被加载进任务寄存器TR中。如果使用了分页机制,那么任务使用的页目录表基地址就会加载进控制寄存器CR3中。当前执行任务的状态由处理器的以下内容组成:

  • 所有通用寄存器和段寄存器信息。
  • 标志寄存器EFLAGS、程序指针EIP、控制寄存器CR3、任务寄存器和LDTR寄存器。
  • 段寄存器指定的任务当前执行空间。
  • I/O映射位图基地址和I/O位图信息(在TSS中)。
  • 特权级0、1和2的堆栈指针(在TSS中)。
  • 链接至前一个任务的链指针(在TSS中)。

任务的执行

      软件或处理器可以使用以下方法之一来调度执行一个任务:

  • 使用CALL指令明确地调用一个任务。
  • 使用JMP指令明确的跳转到一个任务(linux内核使用的方法)。
  • (由处理器)隐含地调用一个中断句柄处理任务。
  • 隐含地调用一个异常句柄处理任务。 

      所有这些调度任务执行的方法都会使用一个指向任务门或任务TSS段的选择符来确定一个任务。当使用CALL或JMP指令调度一个任务时,指令中的选择符即可以直接选择任务的TSS,也可以选择存放有TSS选择符的任务门。当调度一个任务来处理一个中断或异常时,IDT中该中断或异常必须是一个任务门,并且其中含有中断或异常处理任务的TSS选择符。 

      当调度一个任务执行时,当前正在运行任务和调度任务之间会自动的发生任务切换操作。在任务切换期间,当前运行任务的执行环境(或称为任务的状态或上下文)会被保存到它的TSS中并且暂停该任务的执行。此后新调度任务的上下文会被加载进处理器中,并且从加载的EIP指向的指令指令处开始执行新任务。

      如果当前执行任务(调用者)调用了被调度的新任务(被调用者),那么调用者的TSS段选择符会被保存在被调用者TSS中,从而提供了一个返回调用者的链接。对于所有80x86处理器,任务是不可递归调用的,即任务不能调用或跳转到自己。

      中断或异常可以通过切换到一个任务来进行处理。在这种情况下,处理器不仅能够执行任务来处理中断或异常,而且也会在中断或异常处理任务返回时自动的切换会被中断的任务中去。这种操作方式可以处理在中断执行时发生的中断。

      作为任务切换操作的一部分,处理器也会切换到另一个LDT,从而允许每个任务对基于LDT的段具有不同逻辑到物理地址的映射。同时,页目录寄存器CR3也会在切换时被重新加载,因此每个任务可以有自己的一套页表。这些保护措施能够用来隔绝各个任务并且防止他们相互干扰。

      使用处理器的任务管理功能来处理多任务应用是任选的。我们也可以使用软件来实现多任务,使得每个软件定义的任务在一个80x86体系结构的任务上下文中执行。

任务管理数据结构

      处理器定义了一下支持多任务的寄存器和数据结构:任务状态段TSS、TSS描述符、任务寄存器TR、任务门描述符和标志寄存器EFLAGS中的NT标志。使用这些数据结构,处理器可以从一个任务切换到另一个任务,同时保存原任务的上下文,以允许任务重新执行。

      1、任务状态段

      用于恢复一个任务执行的处理器状态信息被保存在称为任务状态段(Task State Segment,TSS)的段中,TSS段中各字段可分成两大类:动态字段和静态字段。

      (1)动态字段。当任务切换而被挂起时,处理器会更新动态字段的内容。这些字段包括:

  • 通用寄存器字段。用于保存EAX,ECX,EDX,EBX,ESP,EBP,ESI和EDI寄存器的内容。
  • 段选择符字段。用于保存ES,CS,SS,DS,FS和GS段寄存器的内容。
  • 标志寄存器EFLAGS字段。在切换之前保存EFLAGS。
  • 指令指针EIP字段。在切换之前保存EIP寄存器内容。
  • 先前任务链接字段。含有前一个任务TSS段选择符(在调用、中断或异常激发的任务切换时更新)。该字段(通常也称为后链接字段)允许任务使用IRET指令切换到前一个任务。

      (2)静态字段。处理器会读取静态字段的内容,但通常不会改变它们。这些字段内容是在任务被创建时设置的。这些字段有:

  • LDT段选择符字段。含有任务的LDT段的选择符。
  • CR3控制寄存器字段。含有任务使用的页目录物理基地址。控制寄存器CR3通常也被称为页目录基地址寄存器。
  • 特权级0、1和2的堆栈指针字段。这些堆栈指针由堆栈段选择符(SS0、SS1、SS2)和栈中偏移量指针(ESP0、ESP1和ESP2)组成。注意,对于指定的一个任务,这些字段的值是不变的。因此,如果任务中发生堆栈切换,寄存器SS和ESP的内容将会改变。
  • 调式陷阱T标志字段。该字段位于字节0x64位0处。当设置了该位时,处理器切换到该任务的操作将会产生一个调试异常。
  • I/O位图基地址字段。该字段含有从TSS段开始处到I/O许可位图处的16位偏移值。

       使用调用或跳转指令,任何可以访问TSS描述符的程序都能够造成任务切换。可以访问TSS描述符的程序其CPL数值必须小于或等于TSS描述符的DPL。在大多数系统中,TSS描述符的DPL字段值应该设置成小于3.这样,只有具有特权级的软件可以执行任务切换操作。然而在多任务应用中,某些TSS的DPL可以设置成3,以使得用户特权级上也能进行任务切换操作。

任务切换

      处理器可以使用以下4中方式之一执行任务切换操作:

  • 当前任务对GDT中的TSS描述符执行JMP或CALL指令。
  • 当前任务队GDT或LDT中的任务门描述符执行JMP或CALL指令。
  • 中断或异常向量指向IDT表中的任务门描述符。
  • 当EFLAGS中的NT标志置位时当前任务执行IRET指令。

      当切换到一个新任务时,处理器会执行以下操作:

  1. 从作为JMP或CALL指令操作数中,或者从任务门中,或者从当前TSS的前一任务链接字段(对于由IRET引起的任务切换)中取得新任务的TSS段选择符。
  2. 检查当前任务是否允许切换到新任务。把数据访问特权规则应用到JMP或CALL指令上。当前任务的CPL和新任务段选择符的RPL必须小于或等于TSS段描述符的DPL,或者引用的是一个任务门。无论目标任务门或TSS段描述符的DPL是何值,异常、中断(除了使用INT n指令产生的中断)和IRET指令都允许执行任务切换。对于INT n指令产生的中断将检查DPL。
  3. 检查新任务的TSS描述符是否标注为存在的(P=1),并且TSS段长度有效(大于0x67)。当试图执行会产生错误的指令时,都会恢复对处理器状态的任何改变。这时的异常处理过程的返回地址指向出错指令,而非出错指令随后的一条指令。因此异常处理过程可以处理出错条件并且重新执行任务。异常处理过程的介入处理对应用程序来说是完全透明的。
  4. 如果任务切换产生自JMP或IRET指令,处理器就会把当前任务(老任务)TSS描述符中的忙标志B复位;如果任务切换是由CALL指令、异常或中断产生,则忙标志B不动。
  5. 如果任务切换由IRET产生,则处理器会把临时保存的EFLAGS映像中的NT标志复位;如果任务切换由CALL、JMP指令或者异常或中断产生,则不用改动上述NT标志。
  6. 把当前任务的状态保存到当前任务的TSS中。处理器会从任务寄存器中取得当前任务TSS的基地址,并且把以下寄存器内容复制到当前TSS中:所有通用寄存器、段寄存器中的段选择符,标志寄存器EFLAGS以及指令指针。
  7. 如果任务切换是由CALL指令、异常或中断产生,则处理器就会把从新任务中加载的EFLAGS中的NT标志置位。如果任务切换产生自JMP或IRET指令,就不用改动新加载EFLAGS中的标志。      
  8. 如果任务切换是由CALL、JMP指令或者异常或中断产生的,处理器就会设置新任务TSS描述符中的忙标志B。如果任务切换由IRET产生,则不去改动B标志。
  9. 使用新任务的TSS的段选择符和描述符加载任务寄存器TR(包括隐藏部分)。设置CR0寄存器的TS标志。
  10. 把新任务的TSS状态加载进处理器。这包括LDTR寄存器,PDBR(CR3)寄存器、EFLAGS寄存器、EIP寄存器以及通用寄存器和段选择符。在此期间检测到的任何错误都将出现在新任务的上下文中。
  11. 开始执行新任务。
原文地址:https://www.cnblogs.com/lsf90/p/2376303.html