Chinaunix首页 | 论坛 | 博客
  • 博客访问: 289217
  • 博文数量: 56
  • 博客积分: 3025
  • 博客等级: 中校
  • 技术积分: 534
  • 用 户 组: 普通用户
  • 注册时间: 2008-08-06 17:28
个人简介

Honesty and diligence should be your eternal mates.

文章分类

全部博文(56)

文章存档

2012年(1)

2011年(27)

2010年(20)

2008年(8)

分类: LINUX

2010-11-05 10:40:48

一、内存管理机制概述:

   Linux内存管理采用的是虚拟内存管理方式。早期的X86以实模式的方式工作,程序可直接访问物理内存单元。这样就无法保证系统代码和数据的安全性。引入虚拟内存管理之后,程序只能以虚拟地址访问内存,MMU(内存管理单元)来完成虚拟地址到物理地址的转换。CPU在需要访问内存的时候,并不是把虚拟地址送给内存总线,而是先将虚拟地址交给MMU,MMU将虚拟地址映射为物理地址,然后将物理地址交给内存总线。对于32位的系统,虚拟地址空间为4Gb,0x0-0xFFFFFFFF。其中,高地址的1G空间留给了操作系统,而应用程序使用低地址的3G空间。

   Linux系统采用了分段和分页机制管理内存。分段机制的作用是将逻辑地址转换为线性地址(虚拟地址),而分页则是进一步将线性地址转换为物理地址。

二、分段机制和相关寄存器:

   分段机制的作用:将给出的逻辑地址[段选择符:偏移量]转换为线性地址。
    
   段选择符(存放于段寄存器中)是一个16位长的字段,其中13位为索引号,它其实存放的是段描述符表中该段段描述符对应的位置,可以通过索引号和段描述符表查找到该段的段描述符。段描述符(8字节)中最重要的是Base字段,它是段的起始地址。用这个家伙再加上偏移量就得到了线性地址。

   相关寄存器:

    段寄存器:存放段选择符。
      GDTR(全局段描述符表寄存器):用于存放GDT的线性地址和长度。GDT是全局段描述符表,
                               存放的是全局段描述符表项。
      LDTR(局部段描述符表寄存器):用于存放LDT的线性地址和长度。GDT是局部段描述符表,                                存放的是局部段描述符表项。
      //这儿的全局段和局部段的区别是:全局段可被所有程序访问,而局部段只能由特定的程序访问。

       段选择符中的索引到底指向的是GDTR还是LDTR是由段选择符剩余3位中的T1字段决定。       T1=0,则指向的是GDT,T1=1,则指向的是LDT。

    现在来看看具体的转换过程以加深对上述概念的理解:

    1、给定一个逻辑地址[段选择符:偏移量],从段选择符得到T1。
    2、若T1=0,则从GDTR中得到段描述符表的线性地址和长度。若T1=1,则从LDTR中得到段描述        符表的线性地址和长度。
    3、根据得到的段描述表的线性地址和段选择符中的索引号,我们可以找到对应的段表项。
    4、从该表项中可以得到BASE字段,即段基址。
    5、将段基址和偏移量相加就得到了线性地址。

三、分页机制:

   分页机制主要负责把线性地址转化为物理地址,当然,分页机制最主要的优点是可以把内存分成一小块一小块的页,从而可以防止产生过多的碎片,提高内存利用率。

   控制寄存器CR0中的PG位是分页机制的开关,如果PG=1,则启用分页机制,把线性地址转化为物理地址;如果PG=0,则禁用分页机制,分段机制所产生的线性地址直接被当作物理地址使用。分页机制将线性地址空间和物理地址空间分成固定大小的页。物理地址空间的页称为页框。线性地址空间的页可映射到任意物理地址空间的页框,而且线性地址空间的页和物理地址空间的页框的大小必须相等。386体系的页大小为4K,并在页的边界上对齐。4G的空间,每个页面4K,那么我们有1M个页面。分页机制所用的页表项也就有1M个,每个页表项4个字节,我们需要4M的空间来存储页表。为了不开辟连续的4M空间,386采用了两级页表机制。

   对于低12位的线性地址,可直接作为物理地址使用。高20位的线性地址,又分了两个部分,每一级页机制使用10位。

   第一级,称为页目录,有1K个,每个页目录4个字节,因此占用4K字节的空间,每个页目录里存放着一个页表的首址,因而就有1K个页表。用线性地址的前十位来表示页目录。

   第二级就是页表,它有1K个表项,每个表项4个字节,也占用4K字节的空间。线性地址的中间十位来表示页表。这样,总共就有1K*1K=1M个表项,每个表项存放着页面的起始地址。再用该起始地址加上低12位的线性地址,我们就得到了物理地址。



        上图为页目录项每一位的使用情况。12 31位存放的是页表首址。第0位,若P=0,表示没有属于该目录项的页面存在于内存。P=1则相反。第1位和第2位定义了页面的读写权限第3位PWT位,表示是否采用写透方式(既写内存又写高速缓存)。第4位,是否启用告诉缓存。第5位,访问位,当对页目录访问时,该位为1。第7位是页大小标志位,置1指的是采用扩展分页机制,即页面的大小不再是4KB,而是4MB。第9-11位为Linux系统未使用。

        页表项每位的作用和页目录的类似,不再赘述。

下面我们看一下整个转换过程:

1、CR3中存放着页目录的起始地址,我们把线性地址的前10位乘以4(每个目录项占4个字节)和该起       始地址相加就得到了页表首址。

2、将线性地址的中间10位作为索引,乘以4,与页表首址相加便得到了页表项的地址。

3、我们从页表项中取出页面首址,与线性地址的低12位相加就得到了物理地址。


阅读(899) | 评论(0) | 转发(0) |
给主人留下些什么吧!~~