操作系统分析——_TSS(n)宏解析

在linux内核代码中,会遇到如下的宏定义:

#define _TSS(n) ((((unsigned long) n)<<4)+(FIRST_TSS_ENTRY<<3)) 
#define _LDT(n) ((((unsigned long) n)<<4)+(FIRST_LDT_ENTRY<<3))
#define ltr(n) __asm__("ltr %%ax"::"a" (_TSS(n)))
#define lldt(n) __asm__("lldt %%ax"::"a" (_LDT(n)))

本人之前对_TSS(n)的理解是:
n<<4表示每个任务都由tss,ldt构成;而每个tss和ldt都是一个描述符,各8个字节。
FIRST_TSS_ENTRY <<3 是因为前面有4个gdt表项,共4*8=32个字节
以为计算出来的值是基于gdt的偏移。
但实际上应该这么理解是有错误的,这是因为ltr 指令接受的输入是一个一个段选择子。
我们应该从段选择子的角度来看这个_TSS(n)和_LDT(n)的值。

LTR:

Load Task Register
Opcode	Mnemonic	Description
0F 00 /3	LTR r/m16	Load r/m16 into task register.
Description
Loads the source operand into the segment selector field of the task register. The source operand (a general-purpose register or a memory location) contains a segment selector that points to a task state segment (TSS). After the segment selector is loaded in the task register, the processor uses the segment selector to locate the segment descriptor for the TSS in the global descriptor table (GDT). It then loads the segment limit and base address for the TSS from the segment descriptor into the task register. The task pointed to by the task register is marked busy, but a switch to the task does not occur.

The LTR instruction is provided for use in operating-system software; it should not be used in application programs. It can only be executed in protected mode when the CPL is 0. It is commonly used in initialization code to establish the first task to be executed.

The operand-size attribute has no effect on this instruction.
Loads the source operand into the segment selector field of the task register. The source operand (a general-purpose register or a memory location) contains a segment selector that points to a task state segment (TSS). After the segment selector is loaded in the task register, the processor uses the segment selector to locate the segment descriptor for the TSS in the global descriptor table (GDT). It then loads the segment limit and base address for the TSS from the segment descriptor into the task register. The task pointed to by the task register is marked busy, but a switch to the task does not occur.

The LTR instruction is provided for use in operating-system software; it should not be used in application programs. It can only be executed in protected mode when the CPL is 0. It is commonly used in initialization code to establish the first task to be executed.

The operand-size attribute has no effect on this instruction.

如果这么理解的话,FIRST_TSS_ENTRY<<3表示左移3位,把最后的3个0补出来,3个0表示 特权0,全局描述表。
FIRST_TSS_ENTRY第4项开始+n<<4,每个进程占用两个段描述符,所以n先左移3位 在左移1位,一起拼接成在gdt表中的第几项这个信息。

你可能感兴趣的:(Advanced,OS,操作系统高级教程)