TSS(任务状态段) TSS描述符 任务寄存器(TR) 任务门描述符 学习总结

主要是TSS、TSS描述符、TR和任务门描述符学习总结
1 任务状态段(TSS)
任务状态段(Task-State Segment(TSS)),保存任务状态信息的系统段为任务状态段。图7-2描述32位CPU的TSS信息。TSS主要分为动态字段和静态字段。
这里写图片描述
  在任务切换过程中当任务挂起时,处理器会更新动态字段,动态字段有:
 (1)通用寄存器字段—任务切换之前,EAX,ECX,EDX,EBX,ESP,EBP,ESI,EDI寄存器状态。
 (2)段选择符字段—任务切换之前,ES,CS,SS,DS,FS,GS寄存器保存的段选择符。
 (3)EFLAGS寄存器字段—任务切换之前,EFAGS寄存器的状态。
 (4)EIP字段—任务切换之前,EIP寄存器的状态。
 (5)先前任务链接字段—包含先前任务的TSS的段选择符。该字段禁止任务通过使用IRET指令返回先前的任务。
当任务创建时会创建静态字段,静态字段可读,不可写:
 (1)LDT段选择符字段—包含任务LDT的段选择符。
 (2)CR3控制寄存器字段—包含任务使用的页目录的物理基地址。CR3也被称为page directory base register(PDBR)页目录基址寄存器。
 (3)特权级0,1,2栈指针字段—包含栈段(因为任务运行在不同特权级下,需要不同的栈段,故相应的SS0,SS1,SS2)的段选择符的逻辑地址和栈的偏移(不同特权级相应的ESP0,ESP1,ESP2)。在特定的任务中该字段是静态的,但是如果栈切换发生在单个任务中,SS和EIP的值就会改变。
 (4)T标志(调试陷阱,100字节,位0)—如果设置,当切换任务时,会引起调试异常。
 (5)I/O映射基址字段—是16位的偏移,包含从I/O权限位图和中断导向表中TSS的基地址。

2 TSS 描述符
就像其它段描述符描述段的一些性质一样,TSS描述符用来描述TSS的某些性质。TSS描述符仅可能存放在GDT中,不能存放在LDT或IDT中。32位模式下,TSS描述符格式如下:
当G标志是0时,界限字段的值大于或等于67H(103字节),比TSS(104字节)的大小少一个字节。如果切换到任务的TSS界限字段小于67H会产生无效TSS异常(#TS)。
这里写图片描述

3 任务寄存器(task register)
任务寄存器拥有当前任务的TSS的段选择符和段描述符(32位基地址,16位段界限和描述符参数)。任务寄存器具有可见部分(软件可以读和写)和不可见部分(只能被处理器访问,软件不能读写)。可见部分中的段选择符指向GDT中TSS描述符。不可见部分缓存TSS的描述符。指令LTR(加载任务寄存器)和STR(保存任务寄存器)加载和保存任务寄存器的可见部分。LTR指令让任务寄存器加载TSS描述符的段选择符,该指令只能运行在特权级0,该指令通常用来系统初始化时初始化任务寄存器。指令STR可以将任务寄存器的可见部分保存到通用寄存器或内存中。该指令可以运行在任何特权级。
系统上电或复位时,段选择符和基址指向默认值0,界限设为FFFFH。
下图描述了,任务寄存器中可见部分的段选择符加载TSS描述符的段选择符,访问GDT中TSS描述符,通过TSS描述符访问TSS。同时TSS描述符中的基址和界限字段的值又加载到任务寄存器的不可见部分的基址和界限字段,这样做的目的是下次访问该TSS时可以不用通过GDT中的TSS描述符访问TSS,而是直接通过缓存在任务寄存器中的基址和界限字段访问TSS,加快了系统对TSS的访问。
这里写图片描述

4 任务门描述符(Task-Gate Descriptor)
任务门描述符用来间接地、保护引用任务。结构如下图。任务门描述符可以放在GDT,LDT和IDT中。任务门描述符中的TSS段选择符字段指向GDT中的TSS描述符。在任务切换过程中,任务门描述符中DPL字段控制访问TSS描述符。当程序通过任务门调用和跳转到一个任务时,CPL和门选择符的RPL字段必须小于等于任务门描述符中的DPL。
这里写图片描述
任务可以通过任务门描述符或TSS描述符被访问。LDT中任务门,GDT中的任务门和IDT中任务门可指向相同的任务,如下图:
这里写图片描述
good luck!

  • 4
    点赞
  • 40
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
首先,需要了解一下全局描述符表(Global Descriptor Table,GDT)是什么。GDT是在操作系统启动时由CPU初始化的一个数据结构,用于管理内存段的访问权限。操作系统可以通过修改GDT来控制内存的访问权限和保护。 在Linux系统中,GDT的初始化是在setup.s文件中完成的。下面是setup.s文件中初始化GDT的代码和注释: ``` /* * 初始化GDT */ init_gdt: lgdt gdtr /* 加载GDT寄存器 */ /* GDT表项0:空描述符 */ gdt_null: .word 0, 0 .byte 0, 0, 0, 0 /* GDT表项1:内核代码段描述符 */ gdt_code: .word 0xffff, 0 /* 段界限 */ .byte 0, 0, 0x9a, 0xcf /* 基地址为0,代码段可读可执行,DPL为0,系统段,粒度为4KB */ /* GDT表项2:内核数据段描述符 */ gdt_data: .word 0xffff, 0 /* 段界限 */ .byte 0, 0, 0x92, 0xcf /* 基地址为0,数据段可读可写,DPL为0,系统段,粒度为4KB */ /* GDT表项3:用户代码段描述符 */ gdt_user_code: .word 0xffff, 0 /* 段界限 */ .byte 0, 0, 0x9a, 0xcf /* 基地址为0,代码段可读可执行,DPL为3,用户段,粒度为4KB */ /* GDT表项4:用户数据段描述符 */ gdt_user_data: .word 0xffff, 0 /* 段界限 */ .byte 0, 0, 0x92, 0xcf /* 基地址为0,数据段可读可写,DPL为3,用户段,粒度为4KB */ /* GDT表项5:TSS描述符 */ gdt_tss: .word 0x67, 0 /* 段界限 */ .byte 0, 0, 0x89, 0x40 /* 基地址为tss_entry,DPL为0,系统段,粒度为1B */ .word 0 /* tss_entry的低16位 */ .byte 0 /* tss_entry的第24位 */ .byte 0x00 /* tss_entry的第32位 */ .word 0 /* tss_entry的高16位 */ /* GDT表项6:LDT描述符 */ gdt_ldt: .word 0, 0 /* 段界限 */ .byte 0, 0, 0x82, 0x40 /* 基地址为ldt,DPL为0,系统段,粒度为1B */ /* GDT表项7:TSS段 */ gdt_tss_entry: .word 0, 0 /* 填充 */ .word 0x10, 0 /* ss0 */ .byte 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0 /* 填充 */ /* GDT表项8:LDT段 */ gdt_ldt_entry: .word 0, 0 /* 填充 */ .byte 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0 /* 填充 */ /* GDT表项9:TSS段 */ gdt_tss2_entry: .word 0, 0 /* 填充 */ .word 0x10, 0 /* ss0 */ .byte 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0 /* 填充 */ /* GDT表项10:LDT段 */ gdt_ldt2_entry: .word 0, 0 /* 填充 */ .byte 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0 /* 填充 */ /* GDT表项11:TSS段 */ gdt_tss3_entry: .word 0, 0 /* 填充 */ .word 0x10, 0 /* ss0 */ .byte 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0 /* 填充 */ /* GDT表项12:LDT段 */ gdt_ldt3_entry: .word 0, 0 /* 填充 */ .byte 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0 /* 填充 */ .fill 16 * 8 - (. - init_gdt) /* 填充到16字节 */ /* GDT表 */ gdt: .word 16 * 8 - 1 /* GDT表长度 */ .long gdt /* GDT表地址 */ /* GDT寄存器 */ gdtr: .word 16 * 8 - 1 /* GDT表长度 */ .long gdt /* GDT表地址 */ ``` 上述代码中,首先使用`lgdt`指令将GDT表的长度和地址加载到GDT寄存器中。然后,定义了一些GDT表项,包括空描述符、内核代码段描述符、内核数据段描述符、用户代码段描述符、用户数据段描述符TSS描述符和LDT描述符。其中,每个GDT表项包括段界限、基地址、段属性等信息。 最后,定义了一个GDT表数组`gdt`,将GDT表长度和地址存储在`gdtr`寄存器中,完成了GDT的初始化。 需要注意的是,上述代码只是一个简化的示例,实际的GDT表项可能更加复杂,具体的实现方式也可能因操作系统的不同而有所差异。

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值