日期:2014-05-16  浏览次数:20803 次

linux内存管理解析----linux物理,线性内存布局及页表的初始化

主要议题:

1分页,分段模式及实模式

2Linux分页 

3linux内存线性地址空间布局及物理内存空间布局

4linux页表初始化及代码解析


1.1.1内存寻址和保护模式
在X86平台上,内存控制单元通过分段单元电路把逻辑地址转换为线性地址,又通过分页单元把线性地址转换为物理地址。
 




    一个逻辑地址由段标识符和段内偏移地址组成。段标示符是一个16位长度的字段,称为段选择符,而偏移地址是32位的字段。


 
     一般用段寄存器来保存段选择符,如CS,DS,ES,SS等,CS段选择符中用RPL来表示CPU当前的特权级别,0表示工作在内核态,3标示工作在用户态。每个段由一个8个字节的描述符进行管理,段描述符表放在GDT或者LDT中,通常只定义一个GDT,而每个进程除了GDT中的段外还需要创建附加的段,就可以有自己的LDT段,通常GDT段存放在GDTR控制寄存器中。


每当一个段选择符被加入到段寄存器时,段描述符就被自动加载到非编程寄存器中.
 


实模式由于是由8086/8088发展而来因此他更像是一个运行单片机的简单模式,计算机启动后首先进入的就是实模式,通过8086/8088只有20根 地址线所以它的寻址范围只有2的20次幂,即1M。内存的访问方式就是我们熟悉的seg:offset逻辑地址方式,例如我们给出地址逻辑地址它将在 cpu内转换为20的物理地址,即将seg左移4位再加上offset值。例如地址1000h:5678h,则物理地址为 10000h+5678h=15678h。实模式在后续的cpu中被保留了下来,但实模式的局限性是很明显的,由于使用seg:offset逻辑地址只能 访问1M多一点的内存空间,在拥有32根地址线的cpu中访问1M以上的空间则变得很困难。而且随着计算机的不断发展实模式的工作方式越来越不能满足计算机对资源(存储资源和cpu资源等等)的管理,由此产生了新的管理方式——保护模式。
存储方式主要体现在内存访问方式上,由于兼容和IA32框架的限制,保护模式在内存访问上延用了实模式下的seg:offset的形式(即:逻辑地址), 其实seg:offset的形式在保护模式下只是一个躯壳,内部的存储方式与实模式截然不同。在保护模式下逻辑地址并不是直接转换为物理地址,而是将逻辑 地址首先转换为线性地址,再将线性地址转换为物理地址。


1.1.2linux分段:
运行在用户态的所有linux进程都使用同一对相同的段对指令和数据寻址,这两个段就是所谓的用户代码段和用户数据段,类似的,运行在内核态的所有linux进程都使用一对相同的段进行指令和数据的寻址:分别叫做内核代码段和内核数据段。从下图中可以看出linux下逻辑地址和线性地址其实是一致的。


 
  每个处理器都有一个gdtr的寄存器,所有的gdt都存放在cpu_gdt_table数组里面,而所有GDT的地址和他们的大小都被存放在cpu_gdt_descr数组中。


1.1.3linux分页:
  在cpu中通过cr3寄存器来切换对应的页表。
  下面是线性地址和页表之间的关系,反应了如何从一个线性地址找到一个物理页面,并定位到相关字节。这个表反应的是32位86x86的映射机制:


 
   对于64位cpu的页表管理,一般使用三级或者四级页表,X86_64使用的是四级页表,几级页表主要是根据CPU硬件规格来制定的。
   在linux内核中,统一使用四级页表的数据结构来描述cpu的页表结构,以达到代码的统一。请注意,这里仅仅是用了四级页表来进行描述cpu的页表结构,不代表硬件上就是四级页表,这里是逻辑上的四级。比如,32位的X86是两级页表,它要用四级页表来表示的话,页上级和页中间目录的位数就是为0,在实际的代码中对应的页上级目录和页中间目录都只有一项,其地址和其所属的页全局目录的项是一样的.......


 
1.1.4linux物理内存布局


 
其中,不可用页框(页框0)主要是用来存放bios加电自检期间检测到的硬件配置,0x9f~0x100页框即(640K~1M)留给bios例程,用来映射ISA图形卡上的部分内存,_text表示地址0x100000,即1M用来存放内核的代码段,_etext和_edata之间