linux内核源代码学习(2)内存映射模式终于搞清楚了
来源:互联网 发布:饼状图如何显示数据 编辑:程序博客网 时间:2024/05/16 15:47
2009-08-12 00:38我发表于百度空间,今天移过来
linux内核源代码学习(2)内存映射模式终于搞清楚了
------flyli
今天通过不断的读《linux内核代码情景分析》和在网上查阅资料,终于把内存映射的总得机理高清楚了
下面是我参考的一篇文章(cttnbcj兄弟在csdn上发的一篇帖子,具体地址为http://topic.csdn.net/u/20081011/07/a3d92bd2-19d5-4e25-89c3-bf8f7308bcef.html)
=====================================
段xxxx:偏移yyyyyyyy
首先,xxxx是无法表示段的基址的,对于这个地址,首先要看xxxx的TI位是否为0(即xxxx的第二位),如果是,则从GDTR中获取GDT的基 址,然后在GDT中以段选择器xxxx的高12位得出索引,根据索引偏移找到相应的段描述符,段描述符包括段的基址,限长,优先级各种属性,这就得到了段 的起始地址,加上yyyyyyyy即是要找的内存的线性地址zzzzzzzz。 如果TI位为1,则表示段描述符放在LDT中,第一步的操作还是从GDTR中获取GDT的基址,然后从LDTR寄存器获得索引(非XXXX的高十二位), 注意,这时根据索引偏移得到得并不是段描述符,而是得到LDT段的位置,然后根据xxxx的高十二位从LDT段中获得段描述。再以这个段描述符信息得到段 基址,再加上偏移yyyyyyyy得到要找的线性地址zzzzzzzz。可以写个简单的模拟程式来表示:
if( xxxx的第二位==1 ) //段描述符的位置在GDTR中
{
A1=(GDTR的前三十二位); //把GDTR的基址给A1
段描述符=A1+(xxxx的高12位); //可获得段描述符
线性地址 = 段描述符中的基址+yyyyyyyy;
}
else //TI位为0,表示在段描述符在LDT中
{
A1=(GDTR的前三十二位);
A2=A1+LDTR; //A2即是LDT描述符表的入口,注:LDTR是16位的 (自己注释:GDTR只有一张表,而且基地址(在内核中)确定的,任务切换时候,也不会改变!每个LDTR又是指向自己任务的,所以任务切换时候,只是改 变LDTR寄存器中的内容(改变在GDT中的索引),找到另一个LDT段的描述符(包含了LDT的开始基地址和界限),然后加上段选择子的索引,找出地址 中的位置!),还要要注意的是LDT表的基地址和界限是在LDT的高速缓存中,任务不切换的话,v高速缓存高速缓存的内容不会变!
段描述符=A2+(xxxx的高十二位) //LDT描述符表入口加上偏移,即是相应的段描述符 自己注释:书上写的A2(应该是表示从LDT的开始基地址吧)LDT的基地址+索引才是局部描述符正确的位置
线性地址 = 段描述符中的基址+yyyyyyyy;
}
========================================
原来GDT和LDT之所以一个叫Global(全局)一个叫Local(局部)是因为其实局部的描述表LDT仅仅是GDT的一个引索而已,
为什么要有一个GDTR,并且GDTR的结构和LDTR不一样呢?
这主要是因为系统只有一个GDT,而GDT的描述符有不能存放在GDT中(LDT的描述符都存放在GDT中),所以就需要一个GDTR来指示GDT在内存中的位置。因为GDTR是直接指示内存地址,而LDTR主要指示LDT描述符在GDT中的位置和属性,所以GDTR和LDTR的结构也不同。
下面是我参考的一篇文章(cttnbcj兄弟在csdn上发的一篇帖子,具体地址为http://topic.csdn.net/u/20081011/07/a3d92bd2-19d5-4e25-89c3-bf8f7308bcef.html)
=====================================
段xxxx:偏移yyyyyyyy
首先,xxxx是无法表示段的基址的,对于这个地址,首先要看xxxx的TI位是否为0(即xxxx的第二位),如果是,则从GDTR中获取GDT的基 址,然后在GDT中以段选择器xxxx的高12位得出索引,根据索引偏移找到相应的段描述符,段描述符包括段的基址,限长,优先级各种属性,这就得到了段 的起始地址,加上yyyyyyyy即是要找的内存的线性地址zzzzzzzz。 如果TI位为1,则表示段描述符放在LDT中,第一步的操作还是从GDTR中获取GDT的基址,然后从LDTR寄存器获得索引(非XXXX的高十二位), 注意,这时根据索引偏移得到得并不是段描述符,而是得到LDT段的位置,然后根据xxxx的高十二位从LDT段中获得段描述。再以这个段描述符信息得到段 基址,再加上偏移yyyyyyyy得到要找的线性地址zzzzzzzz。可以写个简单的模拟程式来表示:
if( xxxx的第二位==1 ) //段描述符的位置在GDTR中
{
A1=(GDTR的前三十二位); //把GDTR的基址给A1
段描述符=A1+(xxxx的高12位); //可获得段描述符
线性地址 = 段描述符中的基址+yyyyyyyy;
}
else //TI位为0,表示在段描述符在LDT中
{
A1=(GDTR的前三十二位);
A2=A1+LDTR; //A2即是LDT描述符表的入口,注:LDTR是16位的 (自己注释:GDTR只有一张表,而且基地址(在内核中)确定的,任务切换时候,也不会改变!每个LDTR又是指向自己任务的,所以任务切换时候,只是改 变LDTR寄存器中的内容(改变在GDT中的索引),找到另一个LDT段的描述符(包含了LDT的开始基地址和界限),然后加上段选择子的索引,找出地址 中的位置!),还要要注意的是LDT表的基地址和界限是在LDT的高速缓存中,任务不切换的话,v高速缓存高速缓存的内容不会变!
段描述符=A2+(xxxx的高十二位) //LDT描述符表入口加上偏移,即是相应的段描述符 自己注释:书上写的A2(应该是表示从LDT的开始基地址吧)LDT的基地址+索引才是局部描述符正确的位置
线性地址 = 段描述符中的基址+yyyyyyyy;
}
========================================
原来GDT和LDT之所以一个叫Global(全局)一个叫Local(局部)是因为其实局部的描述表LDT仅仅是GDT的一个引索而已,
为什么要有一个GDTR,并且GDTR的结构和LDTR不一样呢?
这主要是因为系统只有一个GDT,而GDT的描述符有不能存放在GDT中(LDT的描述符都存放在GDT中),所以就需要一个GDTR来指示GDT在内存中的位置。因为GDTR是直接指示内存地址,而LDTR主要指示LDT描述符在GDT中的位置和属性,所以GDTR和LDTR的结构也不同。
- linux内核源代码学习(2)内存映射模式终于搞清楚了
- linux内核源代码学习(1)内存映射模式
- Linux内核源代码情景分析-内存管理之恢复映射
- 再谈互斥锁与条件变量!(终于搞清楚了啊!!!!!)
- ftp安装和虚拟用户创建(终于搞清楚了)
- 再谈互斥锁与条件变量!(终于搞清楚了啊!!!!!)
- AT89S5X的ISP电缆终于搞清楚了
- 终于搞清楚了JAX-RPC是什么
- 终于搞清楚Manifest 的解压问题了
- linux 内核源代码学习
- linux内核源代码学习(4)关于一些数据结构和用户内存的管理
- linux内核源代码学习(5)内存页面的换入换出
- linux 内存映射2 内核/用户进程间通信
- 终于搞清楚了Jsp跟Servlet的关系了。
- linux内核空间的内存映射
- Linux内核 内存映射文件机制mmap
- Linux内核地址映射模型-高端内存
- linux 实例分析内核IO内存映射
- ZOJ 1276 纪录路径的DP,生成括号的方法很有效
- linux内核源代码学习(1)内存映射模式
- 程序人生的开始
- 为网站技术“牛”人充电的“牛”文!
- 创意图片
- linux内核源代码学习(2)内存映射模式终于搞清楚了
- 外面的风景
- 生成随机数字
- 漂亮页面
- linux内核源代码学习(4)关于一些数据结构和用户内存的管理
- PL项目管理:时间管理
- linux内核源代码学习(3)关于一些数据结构和一个理解 错误
- CFileDialog 打开文件
- 刚刚偷的关于XML的教程