TSS
Contents
概念
任务寄存器(TR)用于寻址一个特殊的任务状态段(Task State Segment,TSS)。TSS中包含着当前执行任务的重要信息。 TR寄存器用于存放当前任务TSS段的16位段选择符、32位基地址、16位段长度和描述符属性值。它引用GDT表中的一个TSS类型的描述符。指令LTR和STR分别用于加载和保存TR寄存器的段选择符部分。当使用LTR指令把选择符加载进任务寄存器时,TSS描述符中的段基地址、段限长度以及描述符属性会被自动加载到任务寄存器中。当执行任务切换时,处理器会把新任务的TSS的段选择符和段描述符自动加载进任务寄存器TR中。 TSS的使用是为了解决调用门中特权级变换时堆栈发生的变化。 寄存器TR,保存的是gdt的选择子,也就是根据TR的值可以在gdt表中找到对应的tss描述符,tss描述符会指向一个段,这个段足够存储当前CPU的所有寄存器的值,当线程一执行到这里,会将cpu当前寄存器所有的值都存放在这个tss表中 linux2.4之前的内核有进程最大数的限制,受限制的原因是,每一个进程都有自已的TSS和LDT,而TSS(任务描述符)和LDT(私有描述符)必须放在GDT中,GDT最大只能存放8192个描述符,除掉系统用的12描述符之外,最大进程数=(8192-12)/2, 总共4090个进程。
从Linux2.4以后,全部进程使用同一个TSS,准确的说是,每个CPU一个TSS,在同一个CPU上的进程使用同一个TSS。
注意:
对于linux来说(Linux2.4以后)一个cpu核心只使用一个TSS,也就是TR初始化时设置好指向TSS的地址之后,就再也不改变TR的内容了。
对于linux来说tss的价值只在于存放ss和esp的内容,且只有这两个值是在随着进程切换各种变化而变化的,而这两个值的修改的消耗非常低,远低于TR来更换TSS的开销,所以linux中TR只在初始化时指向TSS,此后不再改变。
我们知道,任务切换(硬切换)需要用到TSS来保存全部寄存器(2.4以前使用jmp来实现切换),中断发生时也需要从TSS中读取ring0的esp0,那么,进程使用相同的TSS,任务切换怎么办?
其实2.4以后不再使用硬切换,而是使用软切换,寄存器不再保存在TSS中了,而是保存在task->thread中,只用TSS的esp0和IO许可位图,所以,在进程切换过程中,只需要更新TSS中的esp0、io_bitmap,代码在sched.c中: https://blog.csdn.net/farmwang/article/details/52318185
Author sorvik
LastMod 2020-02-20