什么是任务?
任务是操作系统中的一个基本执行单位,可以是一个进程或者一个线程,代表了系统中的一个活动。
80x86 提供了哪些硬件支持?
80x86 提供了任务状态段(TSS)、任务门描述符(Task-Gate Descriptor)、任务寄存器(Task Register)等硬件支持。
描述符表中与任务相关的描述符有哪些?
描述符表中与任务相关的描述符有任务门描述符(Task-Gate Descriptor)和TSS 描述符(Task-State Segment Descriptor)。
任务切换与过程调用的区别是什么?
任务切换是从一个任务转换到另一个任务,而过程调用是在同一个任务内部的子过程之间的转换。
在多任务系统和Intel架构中,一个任务由两个主要部分组成:任务执行空间和任务状态段(TSS)。
任务执行空间:
代码段: 存储任务的可执行代码。
堆栈段: 包含任务在执行过程中使用的堆栈。每个特权级别可能有自己的堆栈。
数据段: 一个或多个数据段,存储任务的变量和数据。
如果操作系统使用处理器的特权级别保护机制(通常会这样做),每个特权级别都有其自己的独立堆栈。这种分隔确保在不同特权级别下运行的任务不会干扰彼此的数据和执行。
任务状态段(TSS):
TSS指定构成任务执行空间的段。
它还用作存储任务状态信息的位置,当任务被中断或切换时,保留任务的状态。
在多任务系统中,TSS支持任务之间的链接,实现无缝的任务切换。
识别和加载:
每个任务由与其TSS相关的段选择器标识。
当任务被加载到处理器以便执行时,TSS中的关键信息会被加载到任务寄存器(TR)中。这包括TSS的段选择器、基地址、限制和描述符属性。
如果任务实现了分页(分页允许将虚拟地址映射到物理地址),则任务使用的页目录的基地址会被加载到控制寄存器CR3中。CR3保存页目录的物理基地址,使得处理器能够执行虚拟到物理地址的转换。
一个任务由几部分构成?
一个任务由任务状态段(TSS)、描述任务的段选择子和任务的执行空间组成。
任务执行空间包括什么?
任务执行空间包括代码段、数据段、堆栈段等。
为什么会有多个特权级栈空间?
多个特权级栈空间是为了在不同特权级别间进行切换时,保持各自的栈信息。
当前执行任务的状态由以下元素定义:
当前正在执行的任务状态包括哪些内容?
当前正在执行的任务状态包括通用寄存器、段寄存器、EFLAGS 寄存器、指令指针等。
掌握每一个被包含内容的含义?
这些内容包含了任务执行的所有信息,例如寄存器的值、执行位置等。
为什么要包含这些内容?
这些内容是任务切换时保存和恢复任务状态的关键信息。
任务可以通过以下几种方式被软件或处理器调度执行:
这些调度任务的方法都使用一个段选择器来指示将要调度的任务,这个段选择器指向一个任务门或任务的TSS(任务状态段)。在使用CALL或JMP指令调度任务时,指令中的段选择器可能直接选择TSS,或者选择一个包含TSS选择器的任务门。在处理中断或异常时调度任务,中断或异常的IDT(中断描述符表)条目必须包含一个任务门,这个任务门包含了中断或异常处理任务的TSS选择器。
当任务被调度执行时,当前正在运行的任务与被调度的任务之间发生任务切换。在任务切换过程中,当前执行任务的执行环境(称为任务的状态或上下文)被保存在其TSS中,任务的执行被暂停。然后被调度任务的上下文被加载到处理器中,执行该任务的指令从新加载的EIP寄存器指向的地址开始。如果任务自系统上次初始化以来还没有运行过,EIP将指向任务代码的第一条指令;否则,它将指向任务在上次活动时执行的最后一条指令之后的下一条指令。
任务的执行方式有几种?
任务的执行方式有直接调用、任务门调用和中断调用等。
熟悉掌握每一种执行方式的过程?
不同的执行方式涉及到不同的指令和硬件支持,需要了解各自的工作过程。
Linux 0.00 用的是哪种方式?
Linux 0.00 使用了中断调用的方式进行任务切换。
任务可以递归调用吗?为什么?
任务通常不递归调用,因为递归调用可能导致任务状态丢失,同时任务切换时会遇到复杂的状态管理问题。
处理器定义了五种数据结构来处理与任务相关的活动:
任务状态段(Task-State Segment,TSS): TSS是一个数据结构,包含了一个任务的状态信息,如通用寄存器的内容、代码段、数据段和堆栈段的选择符、指向任务局部描述符表(LDT)的选择符等。TSS用于保存和加载任务的状态信息。
任务门描述符(Task-Gate Descriptor): 任务门描述符是一种特殊的门描述符,用于指向TSS或任务门。它可以被用于实现任务切换。
TSS描述符(TSS Descriptor): TSS描述符是GDT(全局描述符表)或LDT(局部描述符表)中的一个条目,指向TSS的起始地址。TSS描述符定义了TSS的位置和属性。
任务寄存器(Task Register): 任务寄存器(TR)是一个控制寄存器,用于存储当前任务的TSS的段选择符。通过LTR(Load Task Register)指令加载TR寄存器。
EFLAGS寄存器中的NT标志: EFLAGS寄存器中的NT(Nested Task)标志用于指示处理器在执行IRET指令时是否应该引发任务切换。当NT标志被设置时,IRET指令将引发任务切换,使任务返回到一个不同的TSS。当NT标志被清除时,IRET指令将被正常执行。
在任务切换期间,处理器更新动态字段。以下是动态字段:
通用寄存器字段: 在任务切换之前,EAX、ECX、EDX、EBX、ESP、EBP、ESI和EDI寄存器的状态。
段选择符字段: 在任务切换之前,ES、CS、SS、DS、FS和GS寄存器中存储的段选择符。
EFLAGS寄存器字段: 在任务切换之前,EFLAGS寄存器的状态。
EIP(指令指针)字段: 在任务切换之前,EIP寄存器的状态。
上一个任务链接字段: 包含前一个任务的TSS的段选择符(在由调用、中断或异常引发的任务切换时更新)。这个字段(有时称为后向链接字段)通过IRET指令允许任务切换回前一个任务。
处理器读取静态字段,但通常不改变它们。这些字段在创建任务时被设置,是静态的。以下是静态字段:
LDT段选择符字段: 包含任务的LDT的段选择符。
CR3控制寄存器字段: 包含任务要使用的页目录的基本物理地址。控制寄存器CR3也被称为页目录基址寄存器(PDBR)。
特权级别0、1和2的堆栈指针字段: 这些堆栈指针由堆栈段的段选择符(SS0、SS1和SS2)和堆栈的偏移量(ESP0、ESP1和ESP2)组成。对于特定任务,这些字段中的值是静态的,而SS和ESP的值如果在任务内发生堆栈切换则会改变。
T(调试陷阱)标志(字节100,第0位): 当设置时,T标志会在任务切换到该任务时引发调试异常。
I/O映射基址字段: 包含从TSS基址到I/O权限位图和中断重定向位图的16位偏移。这些映射(如果存在)存储在TSS的高地址处。
如果使用分页:
避免在处理器在任务切换期间读取的TSS的部分中放置页边界(前104字节)。 如果在这个区域发生边界,处理器可能无法正确执行地址转换。在任务切换期间,处理器读取和写入每个TSS的前104字节(使用从TSS的第一个字节开始的连续物理地址)。因此,在TSS访问开始后,如果104字节的一部分不是物理连续的,处理器将访问错误的信息,而不会生成页故障异常。
与前一个任务的TSS、当前任务的TSS以及每个TSS的描述符表项对应的页应标记为读/写。
如果在任务切换启动之前将包含这些结构的页面放在内存中,任务切换会更快。
TSS描述符只能放置在GDT中,不能放置在LDT或IDT中。如果尝试使用其TI标志设置的段选择符(表示当前LDT)访问TSS,在CALLs和JMPs期间将引发通用保护异常(#GP),在IRETs期间将引发无效的TSS异常(#TS)。如果尝试将TSS的段选择符加载到段寄存器中,也会引发通用保护异常。
LTR(加载任务寄存器)和STR(存储任务寄存器)指令分别用于加载和读取任务寄存器的可见部分:
任务门描述符中的TSS段选择符字段指向GDT中的TSS描述符。此段选择符的RPL字段不被使用。任务门描述符的DPL控制了在任务切换期间对TSS描述符的访问权限。
任务可以通过任务门描述符或TSS描述符进行访问。这两种结构都满足以下需求:
任务只有一个忙标志的需求:因为任务的忙标志存储在TSS描述符中,所以每个任务应该只有一个TSS描述符。但是,可以有多个任务门引用相同的TSS描述符。
需要对任务进行选择性访问:任务门满足了这个需求,因为它们可以存在于LDT中,并且可以有一个与TSS描述符的DPL不同的DPL。如果一个程序或过程没有足够的权限来访问GDT中任务的TSS描述符(通常其DPL为0),那么它可以通过一个DPL较高的任务门访问任务。任务门使操作系统有更多的自由度来限制对特定任务的访问。
需要由独立任务处理中断或异常:任务门也可以存在于IDT中,这允许中断和异常由处理任务来处理。当中断或异常向量指向一个任务门时,处理器切换到指定的任务。图7-7说明了一个存在于LDT中的任务门、一个存在于GDT中的任务门以及一个存在于IDT中的任务门如何都可以指向同一个任务。
处理器在以下四种情况下将执行转移到另一个任务:
当前程序、任务或过程执行JMP或CALL指令,跳转到GDT中的TSS描述符。
当前程序、任务或过程执行JMP或CALL指令,跳转到GDT或当前LDT中的任务门描述符。
中断或异常向量指向IDT中的任务门描述符。
当前任务在EFLAGS寄存器中的NT标志被设置的情况下执行IRET指令。
当前正在执行的任务的状态总是在成功的任务切换发生时被保存。如果任务被恢复,执行将从已保存的EIP值所指向的指令开始,并且寄存器的值会被恢复为任务被暂停时的值。在切换任务时,新任务的特权级不会继承自被暂停的任务。新任务开始执行的特权级由CS寄存器的CPL字段指定,该字段从TSS中加载。
什么时候发生任务切换?
任务切换发生在当前任务需要让出 CPU 执行时间给其他任务时,比如任务主动让出 CPU 或者发生中断时。
发生任务切换时,处理器会执行哪些操作?
处理器会保存当前任务的状态,加载新任务的状态,并跳转到新任务的执行位置。
中断或异常向量指向 IDT 表中的中断门或陷阱门,会发生任务切换吗?
是的,当中断或异常向量指向任务门描述符时,会发生任务切换
在任务切换时,TSS的上一个任务链接字段(有时称为“回链”)和EFLAGS寄存器中的NT标志用于返回到上一个任务。EFLAGS.NT = 1表示当前正在执行的任务嵌套在另一个任务的执行内部。当CALL指令、中断或异常导致任务切换时,处理器将当前TSS的段选择子复制到新任务的TSS的上一个任务链接字段,并将EFLAGS.NT设置为1。
在TSS中,只允许为一个任务保存一个上下文;因此,一旦调用(分派)一个任务,对该任务的递归调用将导致任务的当前状态丢失。TSS段描述符中的忙标志用于防止任务切换的递归调用和随后的任务状态信息丢失。
处理器管理忙标志的方式如下:
在单处理器系统中,当需要将一个任务从链式任务中移除时,可以使用以下过程来移除任务:
如何判断任务是否嵌套?
任务是否嵌套可以通过检查任务的状态段中的忙标志位(Busy Flag)来判断。
什么情况会发生任务嵌套?
任务嵌套通常发生在当前任务正在执行时,又发生了一个中断或异常需要切换到其他任务时。
任务嵌套时修改了哪些标志位?
任务嵌套时,会设置当前任务的 TSS 的忙标志位(Busy Flag)。
任务嵌套时,如何返回前一任务?
在任务嵌套时,可以通过 IRET 指令返回到前一任务。
任务的地址空间由任务可以访问的段组成。这些段包括TSS中引用的代码、数据、栈和系统段,以及任务代码访问的任何其他段。这些段被映射到处理器的线性地址空间中,而线性地址空间又被映射到处理器的物理地址空间中(可以直接映射或通过分页)。
任务可以以以下两种方式映射到线性地址空间和物理地址空间中:
所有任务共享一个线性到物理地址空间的映射。 — 当未启用分页时,这是唯一的选择。在没有分页的情况下,所有线性地址映射到相同的物理地址。当启用分页时,可以通过为所有任务使用一个页目录来实现这种形式的线性到物理地址空间映射。如果支持按需分页的虚拟内存,线性地址空间可能超过可用的物理空间。
每个任务都有自己的线性地址空间,映射到物理地址空间。 — 通过为每个任务使用不同的页目录来实现这种映射形式。由于任务切换时会加载PDBR(控制寄存器CR3),因此每个任务可以有一个不同的页目录。不同任务的线性地址空间可以映射到完全不同的物理地址。如果不同页目录的条目指向不同的页表,而页表又指向物理内存的不同页面,那么这些任务就不共享物理地址。
为了允许任务之间共享数据,可以使用以下技术为数据段创建共享的逻辑到物理地址空间映射:
通过GDT中的段描述符 — 所有任务必须能够访问GDT中的段描述符。如果GDT中的某些段描述符指向线性地址空间中映射到所有任务共有的物理地址空间区域的段,那么所有任务就可以共享这些段中的数据和代码。
通过共享的LDT — 如果两个或更多任务的TSS中的LDT字段指向同一个LDT,那么它们可以使用相同的LDT。如果共享的LDT中的某些段描述符指向映射到物理地址空间共有区域的段,那么这些段中的数据和代码可以在共享该LDT的任务之间共享。这种共享方法比通过GDT共享更为具体,因为可以将共享限制在特定任务之间。系统中的其他任务可能有不同的LDT,它们无法访问共享的段。
通过映射到线性地址空间中共同地址的不同LDT中的段描述符 — 如果线性地址空间中的这个共同区域在每个任务的物理地址空间中映射到相同的区域,那么这些段描述符允许任务共享段。这些段描述符通常被称为别名。这种共享方法比上面列出的更为具体,因为LDT中的其他段描述符可能指向不共享的独立线性地址。
什么是任务地址空间?
任务地址空间是指任务可以访问的内存地址范围,包括代码段、数据段、堆栈段等。
任务地址空间包括什么?
任务地址空间包括了任务可以访问的所有内存段,这些段可以映射到线性和物理地址空间。
了解把任务映射到线性和物理地址空间的方法?
任务可以通过段描述符和页表等机制将自身的地址空间映射到线性和物理地址空间。
了解任务逻辑地址空间,及如何在任务之间共享数据的方法?
任务的逻辑地址空间可以通过共享段描述符或者使用相同的线性地址映射到相同的物理地址,从而实现任务之间的数据共享。