全部博文(97)
分类: LINUX
2011-10-24 14:25:41
GDT本身不是段,它只是线性地址空间的一个数据结构。每个GDT的线性基址和它的大小限制都必须通过lgdt指令加载到GDTR寄存器中。
源码cpu_init中,对于GDT的初始化:
int ;
int ;
/*
* Initialize the per-CPU GDT with the boot GDT,
* and set up the GDT descriptor:
*/
();
/////
/*
* Current gdt points %fs at the "master" per-cpu area: after this,
* it's on the real one.
*/
void (int )这里的cpu变量指的是某个cpu如果系统是多处理器的话,这里会对每个cpu都有相应的gdt初始化。
{
struct ;
. = (long)();
. = - 1;
(&);
/* Reload the per-cpu base */
();
}
其中,描述GDT的线性基址和大小限制的数据结构即为desc_ptr
struct {
unsigned short ;
unsigned long ;
} (()) ;
详细查看load_gdt。也就是加载GDT的宏:
#define () ()
static void (const struct *)
{
asm volatile("lgdt %0"::"m" (*));
}
详细看下GDT_SIZE:
#define ( * 8)
/*
* The GDT has 32 entries
*/
#define 32
也就是GDT有32项。每项占8个字节。其中,包括18个段描述符和14个空的、未使用、保留的项。
详细的布局见图:
图中,可以看到段选择符这里就起到了索引的作用。通过它可以在GDT表中查找相应的段描述符的信息。
可以看到图中有LDT的描述项。LDT。也就是local descriptor table。GDT必须包含LDT的项。如果有多个LDT,那么GDT中必须有单独的多个来描述相应的LDT。
为什么会有局部描述符表?我的理解是,在纯粹的linux程序的环境下,是可以通过GDT统一管理,而不需要其他的支持就可以了。但是当需要提供对于某些其他非linux环境下的程序,他们在linux环境下运行,可能单单靠GDT是不够的。可能还需要专门的描述符表来针对这类程序提供支持。于是就有了局部描述符表。
图中,比较熟悉的还有内核数据段描述符、内核代码段描述符,用户数据段描述符、内核代码段描述符。以及TSS:任务状态段。
2. 利用段描述符检验段的访位权限和范围,以便确定该段是可访问的并且偏移量位于段的段界限内。