Chinaunix首页 | 论坛 | 博客
  • 博客访问: 1727901
  • 博文数量: 782
  • 博客积分: 2455
  • 博客等级: 大尉
  • 技术积分: 4140
  • 用 户 组: 普通用户
  • 注册时间: 2011-04-06 21:37
个人简介

Linux ,c/c++, web,前端,php,js

文章分类

全部博文(782)

文章存档

2015年(8)

2014年(28)

2013年(110)

2012年(307)

2011年(329)

分类:

2011-08-15 16:52:48

这是一篇读记,我保证写的通俗、连贯,但仅仅想从这篇博文就系统的学习到内核相关知识,你一定会失望的,如果你有内核的学习经验,这篇博文一定会对你的理解和记忆有所帮助。
 
 
第二章 内存寻址:
 
内存控制单元(MMU)通过一种称为分段单元(segmentation unit)的硬件电路、分页单元(paging unit),将逻辑地址转换成物理地址。
 
一个逻辑地址有两部分组成: 一个段选择符(segment selector)(16bit)和一个指定段内相对地址的偏移量(32bit)。
 
cs代码段寄存器、ds数据段寄存器、ss程序栈段寄存器。剩下的三个寄存器es、fs、gs做一般用途,可以指向任意数据段。
此外cs寄存器还有一个很重要的功能:它含有一个两位的RPL字段,用来指明当前cpu的特权级(Current Privilege Level, CPL)。 0 - 最高级, 3- 最低级,在linux只用 0、3 分别代表 内核态、用户态。
 
每个段有一个段描述符(8B)(不是段选择符,刚开始读的时候就混淆了概念。),放在全局描述符表里(Global Descriptoy Tabel,GDT)或局部描述符表(Local Descriptor Tabel, LDT)中。
 
通常只定义一个GDT,而每个进程除了存放在GDT的段之外如果还需要创建附加的段,就可以由自己的LDT,GDT在主存中的地址和大小存放在gdtr控制寄存器中,当前正被使用的LDT的地址和大小存放在ldtr中。
 
关于段描述符各字段的我就不在这里描述了,下面列出linux广泛使用的三种段的类型和对应的段描述符。
1、数据段描述符 可以存放在 GDT、LDT上,设置S标志位为1,表示其不是一个系统段,只是一个普通的数据段。
2、代码段描述符 可以存放在 GDT、LDT上,设置S标志位为1
3、系统段描述符(TSSD) 表示这个段描述符代表一个任务状态段(Task State Segment,TSS),也就是说这个段用于保存处理器寄存器的内容。只能出现在GDT上,S为0,根据相应的的进程是否正在使用CPU,其type字段分别为11或者9.
 
 
回忆一下:逻辑地址由16位段选择符和32位偏移量组成 段寄存器仅仅存放段选择符(16bit),为了加速逻辑地址到线性地址的转换。处理器提供一种附加的非编程寄存器(不能被程序员设置的寄存器),供6个可编程的段寄存器使用。每一个非编程的寄存器含有段描述符(8B),由相应的段寄存器中的段选择符来制定。每当一个段选择符(16bit)被装入段寄存器时,每当一个段选择符被装入段寄存器时,相应的段描述符就由内存装入到对应的非编程CPU寄存器中。
上面最大的优点就是可以绕过LDT、GDT,只需直接引用段描述符的非编程寄存器,但是当段寄存器的内容改变时,需要访问GDT、LDT。
 
一个段描述符的在GDT或LDT中相对的地址是由段选择符的高13位的字段的索引值乘以段描述符的长度(8B)得到的。例如:如果GDT在0x00020000(这个值保存在gdtr寄存器中),且由段选择符所制定的索引号为2,那么相应的段描述符的地址是0x00020000+(2*8)或0x00020010
 
下面的图详细说明了 分段单元是如何将逻辑地址转换成线性地址的
1、首先通过TI字段,了解描述符在哪一个描述符表里。0 - GDT(分段单元从gdtr得到GDT的线性基地址),1 - 被激活的LDT(分段单元从ldtr得到LDT的线性基地址),
2、将段选择符 index*8,再将这个结果与gdtr或ldtr中的内容相加。
3、把逻辑地址的偏移量与段描述符Base字段的值相加就得到了线性地址。
注意,有了段不可编程寄存器之后,只有当段寄存器的内容发生改变时,才需执行前俩操作。
 
Linux 以非常有限的方式使用分段,甚至,分段和分页在某种程度上有些多余,因为他们都可以划分进程的物理地址空间:分段可以给每一个进程分配不同的线性地址空间,而分页可以把统一地址空间映射到不同的物理空间。与分段相比,linux更喜欢分页,因为;
1、当所有进程使用相同的段寄存器值时,内存管理变得简单,也就是说它们能共享同样的一组线性地址(这正是因为他们的段寄存器中的值是相等的)。
2、linux希望享有良好的移植性,然后RISC(精简指令集,相对还有CISC)体系结构对分段的支持很有限。
2.6版本只有在80X86结构下才需要使用段。
 
 
 
 
 
 
 
阅读(287) | 评论(0) | 转发(0) |
给主人留下些什么吧!~~