分享

linux内存管理

 心不留意外尘 2016-07-07
http://blog./uid-27164517-id-3282863.html

2012
         分页就是将进程的逻辑地址空间分成若干大小相等的片(即页),然后装入内存。 分段就是用户可以把自己的作业按逻辑关系划分为若干个段,每个段都是从0开始编址,并有自己的名字和长度。这就相当于程序里边的主函数段、各个子函数段、数据段、栈段等等。 要知道在引入分页和分段之前,是通过连续分配方式来管理存储器的,就是说一个进程在内存中是连续存放的。 可以这样理解吧,内存中有进程1、2、3……进程2先执行完成了,然后释放了所占有的内存空间,而之后, 如果新调入的进程内存需求大于之前2所占有的内存空间,那么不可能利用这块内存,相对于内存需求更大的进程来说,之前2所占有的内存空间就是不能利用的碎片, 如果新调入的进程内存需求小于之前2所占有的空间就会留下空隙,也会带来碎片。 虽然可以通过“紧凑”的方法进行碎片整理,但开销很大这就产生了与连续分配方式相对的离散分配方式,便先后引入了分页和分段存储管理。 所以相同点就是,两者都属于存储器管理方式中的离散分配方式。都要通过地址映射机构来实现地址变换。 不同点就在于,离散分配方式的基本单位的不同,是页还是段。 页是信息的物理单位,段是信息的逻辑单位。 分页的作业地址空间是一维的,线性的,程序员只需利用一个记忆符表示一个地址;而分段的作业地址空间是二维的,程序员在表示一个地址的时候既要给出段名,又需要给出段内陆址。其中,段名可以理解为函数名等,段内陆址可以理解程变量等的地址。 值得一提的是其中页的大小要和物理块或者页框一样,而物理块是操作系统定好了的。也就是说你的操作系统装完之后,物理块的大小是定了的,从而页的大小也是定了的。而段的长度是不定的。 引入分页存储管理方式的目的是提高内存利用率,而引入分段存储是为了满足用户(程序员)在编程和使用上多方面上的要求。还有将两者结合一起的段页式系统。


一,linux绕过了段机制而主要采用了页机制实现内存管理。原因如下:
            1,为了使得内存管理变得简单,绕过了段机制,虚拟地址=线性地址。
            2,为了方便移植到多个硬件平台,因为很多RISC处理器不支持段机制。
----------------------------------------------------------------------------------------------
二,进程的地址空间。

    linux下每个进程都有4GB的地址空间=1GB的内核空间  + 3GB的用户空间
    1,进程切换时,虚拟地址空间也随之切换。唯有3GB的用户空间切换,1GB的内核空间
          是所用进程共享的,常驻内存。
    2,虚拟地址空间切换,页表也随之切换。
----------------------------------------------------------------------------------------------
三,虚拟地址映射到物理地址。

      地址映射应该分两部分分析,内核空间和用户空间。
      内核空间使用的是线性映射,很好理解。
      用户空间使用的是页表来映射。
 ---------------------------------------------------------------------------------------------   
          3.1,内核空间的地址映射到物理地址空间。
    
  内核空间地址映射函数如下:

  1. #define __va(x) ((void *)((unsigned long)(x) PAGE_OFFSET))  // 虚拟地址 = 物理地址x 3GB
  2. #define __pa(x) ((unsigned long) (x) - PAGE_OFFSET)                  //物理地址  = 虚拟地址x -  3GB 
----------------------------------------------------------------------------------------------
   
               3.2,用户空间映射到物理地址空间。
        linux 采用了三级页表,实际上linux可以通过启用或禁用中间目录来启用两级和
       三级分页(使用相同的代码),在32位的x86体系上就用的两级页表。
 
----------------------------------------------------------------------------------------------
          先以两级页表说说虚拟地址是如何映射成为物理地址的吧。

         
               进程切换,首先是从新的进程的PCB中读出pgd,然后写入CR3中,cr3 = __pa(pgd)
 CR3相当于页表的根所在,CR3中存放的是页目录的基址,该基址 偏移量(线性地址的前10位)
  = 页表的基址,页表的基址 偏移量(线性地址的中间10位)=物理页的基址,物理页的基址
 偏移量 = 物理地址。

下面小结物理地址的计算:

  1. cr3 Page Directory (10 MSB) = 指向 table_base
  2. table_base Page Table (10 中间位) = 指向 page_base
  3. page_base Offset = 物理地址 (获得页框)        
                                            

    本站是提供个人知识管理的网络存储空间,所有内容均由用户发布,不代表本站观点。请注意甄别内容中的联系方式、诱导购买等信息,谨防诈骗。如发现有害或侵权内容,请点击一键举报。
    转藏 分享 献花(0

    0条评论

    发表

    请遵守用户 评论公约

    类似文章 更多