os读书笔记4
任务管理
4.1任务管理概述
• 什么是任务?
任务通常指的是一个正在执行的程序或程序的一部分,任务是处理器可以调度、执行和挂起的工作单元。每个任务都拥有自己的需求和目标,并且任务自身由一系列的指令构成。这些指令都是由计算机的CPU来执行的。
• 80x86
提供了哪些硬件支持?
IA-32 体系结构提供了一种机制,用于保存任务的状态、调度任务以执行以及用于从一个任务切换到另一个任务。
在保护模式下运行时,所有处理器执行都从在任务中。即使是简单的系统也必须定义至少一个任务。更复杂的系统可以使用处理器的支持多任务应用程序的任务管理工具。
• 描述符表中与任务相关的描述符有哪些?
主要有TSS(Task-State Segment)、Task Register、CR3寄存器
• 任务切换与过程调用的区别是什么?
任务切换是指在多任务操作系统中,从当前任务切换到另外一个任务的过程(Task Swithing),这个切换过程伴随着上下文的切换,由操作系统执行的。而过程调用是一段代码调用另一段代码的过程,不会有上下文的切换,但是有栈帧的变动,用于实现模块化的程序设计。
4.1.1. 任务的结构
• 一个任务由几部分构成?
一个任务主要由五部分构成:
-
TSS任务段
-
任务门描述符
-
任务段描述子
-
任务寄存器
-
EFLAGS中的NT标志位寄存器
• 任务执行空间包括什么?
需要两部分,一部分是动态空间,另一部分是静态空间。
动态空间:
动态空间里主要包括
寄存器、内存堆栈、地址映射、链接部分等。
静态空间:
静态空间主要包括CR3控制器、特权等级空间、I/O map映射区域等
• 为什么会有多个特权级栈空间?
区分多个特权级栈空间是为了实现操作系统的特权级别和保护机制。
在操作系统中,通常会划分为多个特权级别,如内核态和用户态。内核态具有较高的特权级别,可以执行特权指令和访问受限资源,而用户态的特权级别较低,只能执行受限的操作。为了实现这种特权级别的划分,需要为每个特权级别分配独立的栈空间。
4.1.2. 任务状态
• 当前正在执行的任务状态包括哪些内容?
• 任务的当前执行空间,由段寄存器中的段选择器(CS、DS、SS、ES、FS 和 GS)。
• 通用寄存器的状态。
• EFLAGS寄存器的状态。
• EIP 寄存器的状态。
• 控制寄存器CR3的状态。
• 任务寄存器的状态。
• LDTR登记册的状态。
• I/O 映射基址和 I/O 映射(包含在 TSS 中)。
• 堆栈指针指向权限 0、1 和 2 堆栈(包含在 TSS 中)。
• 链接到以前执行的任务(包含在 TSS 中)。
• 掌握每一个被包含内容的含义?
主要分为了四部分,寄存器、IO映射关系、带有权限等级的堆栈、以前任务的link。
寄存器就不用多说了,记录着当前任务的状态,带有权限等级的堆栈也一样,记录着当前任务的堆栈状态。
这里的IO映射关系实则指I/O Permission Bitmap,也就是I/O许可位图,在TSS段的+102 Bytes偏移处,保存着I/O位图基址的值,每一个任务都有一个I/O位图。
I/O位图保存着一些flags位,用来指示任务是否具有这个IO的访问权限,让同一特权级下的不同任务也可以有不同的I/O访问权限。
以前任务的地址,这个是用来切换任务的,当当前任务执行完毕要切换到之前的任务的时候,通过这个地址来进行访问。
• 为什么要包含这些内容?
具有了这些内容之后,可以流畅优秀地执行上下文切换,也就是从当前任务切换到下一个任务,再从下一个任务切换回当前任务,都能保证任务的执行数据不丢失。
4.1.3. 任务的执行
• 任务的执行方式有几种?
主要有五种
-
使用CALL指令显式返回
-
使用JMP指令显式跳转
-
中断处理隐式跳转
-
对异常处理程序任务的隐式调用
-
在EFLAGS寄存器中设置NT标志时返回(使用IRET指令的时候自动)
• 熟悉掌握每一种执行方式的过程
CALL显示调用:通过压栈弹栈的方式保存上下文,再通过CALL指令改变RIP跳转到任务地址。
JMP指令显示跳转:JMP指令只改变RIP,需要在前面保存好上下文相关信息,JMP可以直接跳转到任务地址。
中断处理隐式跳转:中断处理的时候,程序会自动保存上下文信息,当前任务会滞留,然后操作系统调度器会从准备队列中选出一个新任务,CPU跳转到新任务进行执行,前任务中断处理完成,发出中断,响应中断的时候再返回到前任务。
对异常处理程序任务的隐式调用:和中断处理类似,程序运行抛出异常,操作系统会根据异常处理向量表找到对应的异常处理程序,然后保存上下文,当前任务滞留,CPU选择执行下一任务,之后再返回(可能不返回)。
在EFLAGS寄存器中设置NT标志时返回(使用IRET指令的时候自动):在发生中断或异常时,异常处理程序可以将NT标志设置为使得处理器在返回到外层任务时,可以执行内层任务的处理,所以设置了NT标志,IRET的时候将会自动返回。
• Linux 0.00
用的是哪种方式?
使用的是中断处理隐式跳转的方式。
• 任务可以递归调用吗?为什么?
可以递归调用,比方说中断处理在在跳转到另外任务的时候,又遇到了中断,再次跳转到另外的任务。其TSS里面可以构成一条任务调用链。
4.2. 任务的数据结构
• 任务状态段 Task-State Segment (TSS)
数据结构如下,总长104Bytes
• TSS
描述符
-
TSS(任务状态段):TSS是一种数据结构,包含了任务的上下文和状态信息,用于在任务切换时保存和恢复任务的执行环境。
-
Base(基址):指定了TSS在内存中的起始位置。
-
Limit(限长):指定了TSS在内存中的大小,以字节为单位。限长字段的值需大于等于67H。
-
DPL(描述符特权级):TSS描述符中的DPL字段指定了可以访问该TSS的程序或过程的特权级。只有特权级小于等于TSS描述符的DPL的程序或过程才能调度和切换任务。
-
Granularity(粒度):粒度标志指示了限长字段的粒度,其中0表示限长按字节表示,1表示限长乘以4K(4096)来表示。
-
Present(存在标志):存在标志指示TSS是否在内存中存在。
-
G(Granularity)标志:用于指示限长字段的粒度,默认为0,表示限长按字节表示。
-
I/O Permission Bit Map(输入/输出权限位图):如果在TSS中包含了I/O权限位图,则需要更大的限长来存储这些额外的数据。
• 任务寄存器
任务寄存器如图所示分为三个PART。
通过可见的部分来进行GDT表访问TSS段描述符,再通过不可见部分来进行查询TSS段
• 任务门描述符 Task-Gate Descriptor
-
任务门(Task Gate)描述符:任务门描述符是一种数据结构,提供对任务的间接、受保护的引用。它可以放置在全局描述符表(GDT)、局部描述符表(LDT)或中断描述符表(IDT)中。
-
TSS(任务状态段)段选择符字段:任务门描述符中的TSS段选择符字段指向全局描述符表(GDT)中的一个TSS描述符。
-
RPL(请求特权级):任务门描述符中TSS段选择符字段的RPL字段是不使用的,它不影响任务切换的访问权限。
-
任务门描述符的DPL(描述符特权级):任务门描述符的DPL字段控制任务切换期间对TSS描述符的访问。当一个程序或过程通过任务门进行调用或跳转到一个任务时,任务门选择符的CPL(当前特权级)和RPL字段必须小于等于任务门描述符的DPL。
具体可以参考别的门描述符。
4.3. 任务切换
• 什么时候发生任务切换?
-
当前程序、任务或过程对GDT中的TSS描述符执行JMP或CALL指令。
-
当前程序、任务或过程对任务门描述符执行 JMP 或 CALL 指令GDT 或当前的 LDT。
-
中断或异常向量指向 IDT 中的任务门描述符
-
当前任务在设置 EFLAGS 寄存器中的 NT 标志时执行 IRET
• 发生任务切换时,处理器会执行哪些操作?
-
从JMP或CALL指令的操作数、任务门或先前任务的链接字段(用于由IRET指令发起的任务切换)获取新任务的TSS段选择符。
-
检查当前(旧)任务是否被允许切换到新任务。数据访问特权规则适用于JMP和CALL指令。当前(旧)任务的CPL和新任务的段选择符的RPL必须小于等于所引用的TSS描述符或任务门的DPL。但是,除了INT n指令生成的中断外,异常、中断和IRET指令可以无视目标任务门或TSS描述符的DPL来切换任务。对于由INT n指令生成的中断,会检查DPL。
-
检查新任务的TSS描述符是否标记为存在且具有有效的限长(大于或等于67H)。
-
检查新任务是否可用(通过调用、跳转、异常或中断)或繁忙(通过IRET返回)。
-
检查当前(旧)TSS、新TSS以及任务切换中使用的所有段描述符是否已分页到系统内存中。
-
如果任务切换是通过JMP或IRET指令发起的,处理器会清除当前(旧)任务的TSS描述符中的繁忙(B)标志;如果是通过CALL指令、异常或中断发起的,则保持繁忙(B)标志设置不变。
-
如果任务切换是通过IRET指令发起的,处理器会清除暂时保存的EFLAGS寄存器图像中的NT标志;如果是通过CALL指令、JMP指令、异常或中断发起的,则保持暂时保存的EFLAGS图像中的NT标志不变。
-
将当前(旧)任务的状态保存到当前任务的TSS中。处理器根据任务寄存器中的当前TSS的基址,将以下寄存器的状态复制到当前TSS中:所有通用寄存器,来自段寄存器的段选择符,暂时保存的EFLAGS寄存器图像以及指令指针寄存器(EIP)。
-
如果任务切换是通过CALL指令、异常或中断发起的,处理器将在从新任务加载的EFLAGS中设置NT标志。如果是通过IRET指令或JMP指令发起的,NT标志将反映从新任务加载的EFLAGS中的NT的状态。
-
如果任务切换是通过CALL指令、JMP指令、异常或中断发起的,处理器会设置新任务的TSS描述符中的繁忙(B)标志;如果是通过IRET指令发起的,则保持繁忙(B)标志设置不变。
-
将任务寄存器加载新任务TSS的段选择符和描述符。
-
将TSS状态加载到处理器中。这包括LDTR寄存器、PDBR(控制寄存器CR3)、EFLAGS寄存器、EIP寄存器、通用寄存器和段选择符。在加载此状态的过程中发生故障可能会损坏体系结构状态。(如果未启用分页,会从新任务的TSS中读取PDBR值,但不会加载到CR3中。)
-
加载和验证与段选择符关联的描述符。与此加载和验证相关的任何错误都会在新任务的上下文中发生,并可能损坏体系结构状态。
-
准备执行新任务。
• 中断或异常向量指向 IDT
表中的中断门或陷阱门,会发生任务切换吗?
中断或异常向量指向IDT表中的中断门或陷阱门时,一般情况下不会发生任务切换。任务切换通常是由任务门引起的,并且在通过任务门切换任务时,会执行任务状态的保存和加载操作。但有一种情况下,当通过中断指令(INT n)生成的中断向量引用一个任务门时,可能会发生任务切换。在这种情况下,会根据任务门描述符中的设置进行任务切换,并执行相应的任务。
4.4. 任务链
• 如何判断任务是否嵌套?
可以通过EFLAGS中的NT位来判断是否嵌套,如果是1则是嵌套的。
• 什么情况会发生任务嵌套?
当新任务发生中断、异常、调用、陷阱等情况下会发生任务嵌套。
• 任务嵌套时修改了哪些标志位?
修改了EFLAGS中的NT位,设为了1。
• 任务嵌套时,如何返回前一任务?
如果软件使用 IRET 指令挂起新任务,处理器将检查 EFLAG。NT = 1;然后它使用
“Previous Task Link”字段中的值以返回到上一个任务。
4.5. 任务地址空间
• 什么是任务地址空间?
指任务所能访问的各个段的集合。这些段包括在任务状态段 (TSS) 中引用的代码、数据、栈和系统段,以及任务代码中访问的其他段。这些段被映射到处理器的线性地址空间中,而线性地址空间又被映射到处理器的物理地址空间中(可以直接映射或通过分页实现)。
• 任务地址空间包括什么?
这些段包括在任务状态段 (TSS) 中引用的代码、数据、栈和系统段,以及任务代码中访问的其他段。
• 了解把任务映射到线性和物理地址空间的方法?
主要有两种方法
-
在所有任务之间共享一个线性到物理地址空间映射:当未启用分页机制时,这是唯一的选择。在没有分页的情况下,所有的线性地址都映射到相同的物理地址。当启用分页机制后,可以通过使用一个页目录来实现所有任务共享的线性到物理地址空间映射。线性地址空间可以超过可用的物理空间,如果支持按需分页的虚拟内存。
-
将每个任务拥有独立的线性地址空间,映射到物理地址空间:这种映射方式通过使用每个任务的不同页目录来实现。由于任务切换时会加载PDBR(控制寄存器CR3),因此每个任务可以有不同的页目录。这样,每个任务都可以拥有自己的线性地址空间,并将其映射到物理地址。
解任务逻辑地址空间,及如何在任务之间共享数据的方法?
-
通过全局描述符表(GDT)中的段描述符实现数据段的共享:所有任务都必须能够访问GDT中的段描述符。如果GDT中的一些段描述符指向映射到所有任务共享的物理地址空间区域的线性地址空间段,那么所有任务都可以共享这些段中的数据和代码。
-
通过共享的局部描述符表(LDT)实现数据段的共享:如果多个任务使用相同的LDT,即它们的TSS中的LDT字段指向同一个LDT,那么这些任务可以共享LDT中指向映射到物理地址空间共享区域的段的数据和代码。通过共享LDT实现的数据共享比通过GDT的方式更加灵活和有选择性,因为可以将共享限制在特定的任务之间,系统中的其他任务可能具有不同的LDT,不能访问共享段。
-
通过映射到线性地址空间中相同地址的不同LDT的段描述符实现数据段的共享:如果线性地址空间的某个共享区域被映射到每个任务的物理地址空间的相同区域,那么这些段描述符可以使任务共享段。这些段描述符通常被称为别名。通过这种方式的共享更加有选择性,因为LDT中的其他段描述符可能指向独立的线性地址,不共享。