关于GDT,LDT的问题。
大家好,我现在在看linux0.11进程调度的copy_process()函数,有个和GDT,LDT有关的问题想不明白:linux在启动时,在setup阶段会建立GDT并设置GDTR,其中GDT在内存中的布局如下:
---------------------
.
.
.
---------------------
数据&堆栈段描述符
---------------------
代码段描述符
---------------------
描述符(NULL)
--------------------- ———>局部描述符标LDT0
---------------------
LDTN描述符
---------------------
TSSN描述符
---------------------
.
.
.
---------------------
LDT1描述符
---------------------
TSS1描述符
---------------------
LDT0描述符
---------------------
TSS0描述符
---------------------
系统段描述符(未用)
---------------------
内核数据段描述符
---------------------
内核代码段描述符
---------------------
描述符(NULL)
--------------------- ———>全局描述符标GDT
我的理解是:
1)寻址时指定GDT,通过CS或DS中的选择符,找到GDT表中的LDT(代码段或数据段),然后通过偏移地址和LDT描述符中的段基址,得到32位线形地址。
2)寻址时指定LDT,通过LDTR中的选择符,找到LDT(代码段或数据段)???,然后通过偏移地址和LDT描述符中的段基址,得到32位线形地址。
问题是
1)我不明白这两者有什么区别?这里面肯定有某个地方错了。
2)通过查了些x86分段机制,资料上说LDTR中保存选择符,那么CS或DS中的不是选择符?这个时候不用CS和DS来寻址?
3)寻址过程应该是怎么样的?
4)进程切换的时候,哪些寄存器需要内核重新设置?
另外,我还有一个相关的问题:
1)程序编译时会生成.o文件,其中.o文件中的变量和函数地址和运行时的地址有什么关系?
我的理解是:
.o文件中的代码段和数据段基址都是0x0,程序中的变量和函数地址都是段内偏移。在程序运行的时候,操作系统会为程序分配虚拟页。同时分别把代码段,数据段码读入进程虚拟地址,再更新进程的代码段,数据段基址(线形地址),等待CPU调度。
这个理解对不对?
请各位不吝指教。
[ 本帖最后由 NewCore 于 2008-10-26 20:47 编辑 ]
回复 #1 NewCore 的帖子
LDTR中应该保存的LDT的基地址吧.o文件里的地址就是逻辑地址。运行时通过分段、分页处理转化为物理地址。 原帖由 biger410 于 2008-10-26 21:02 发表 http://linux.chinaunix.net/bbs/images/common/back.gif
LDTR中应该保存的LDT的基地址吧.
o文件里的地址就是逻辑地址。运行时通过分段、分页处理转化为物理地址。
你说这话有根据吗?
这是我从一篇文章摘来的http://blog.chinaunix.net/u1/35334/showart_278335.html
“LDT和GDT从本质上说是相同的,只是LDT嵌套在GDT之中。LDTR记录局部描述符表的起始位置,与GDTR不同LDTR的内容是一个段选择子。由于LDT本身同样是一段内存,也是一个段,所以它也有个描述符描述它,这个描述符就存储在GDT中,对应这个表述符也会有一个选择子,LDTR装载的就是这样一个选择子。”
回复 #3 NewCore 的帖子
是我理解错了,ldtr存放的是ldt的段选择子 唉,原来linux0.11内核在实现上和以后版本相差如此之大.我还是换本书先吧:( :( :(回复 #5 NewCore 的帖子
那读0.11代码到底好不呢?还是直接看2.6的呢? 原帖由 NewCore 于 2008-10-26 21:24 发表 http://linux.chinaunix.net/bbs/images/common/back.gif你说这话有根据吗?
这是我从一篇文章摘来的http://blog.chinaunix.net/u1/35334/showart_278335.html
“LDT和GDT从本质上说是相同的,只是LDT嵌套在GDT之中。LDTR记录局部描述符表的起始位置,与GDT ...
LDTR存放的是LDT的段选择子,LDT是一个存放局部段描述符的内存段
而LDT段的段描述符在GDT中
从GDTR寄存器得到GDT的基地址,然后从LDTR得到LDT段的段描述符,根据跳转什么的指令,从LDT段中获取某个局部段描述符,得到该局部段的基地址之类的信息。。。
回复 #6 可可熊 的帖子
我的意见是,还是直接看2.6吧。0.11可以偶尔作为参考。 0.11 没有什么不好,你看到的每一句代码浓缩度远比新版本高的多,我就在看0.11以下是个人理解:
1)我不明白这两者有什么区别?这里面肯定有某个地方错了。
GDTR ,顾名思义GDT的寄存器,存放GDT表基址的寄存器,LDTR ,顾名思义LDT的寄存器,存放LDT表基址的寄存器。
2)通过查了些x86分段机制,资料上说LDTR中保存选择符,那么CS或DS中的不是选择符?这个时候不用CS和DS来寻址?
LDTR是和进程切换时用的,CS`DS是程序运行的时候使用的
3)寻址过程应该是怎么样的?
实模式和保护模式不同,比较复杂,我不懂
4)进程切换的时候,哪些寄存器需要内核重新设置?
GDTR,LDTR,TSS..
0.11 没有什么不好,其实《自己动手写os》也不错,快速了解一些知识,而且是代码级别的,可以运行,效果直观。
(1) LDTR中的应该是选择子,即GDT中的索引,借此可以找到LDT表所在的页面
(2)关于段寄存器,选择子,段描述符。补充点
intel 32位的机器上,像CS,SS这样的段寄存器分为两个部分,可见部分和不可见部分。可见部分就是常说的段寄存器,防止选择子,不可见部分是也称为描述符缓存。
比如当把kernel_cs赋值给cs的时候,这个时候会把GDT中相应的描述符缓存到cs的不可见区域,以此来提升效率。
页:
[1]