Linux内核代码阅读序列(9)-内存模型 之一

重新开始

2009年的时候信誓旦旦的说要将这个系列坚持写下去,结果未能如愿。抱歉的很。去年前半年奔波劳碌得到处跑,9月以后自己的人生发生了180度的大转弯,自己给自己的shock就已经够大了,更加没有心思写blog。还好还好,上帝给了我一个此前从未有的幸福的开端,也许我可以牵着她的手,安心下来好好补足功课了。愿上帝保佑2010一切都好。愿上帝保佑我能将这个系列按照原来的计划写完。

Linux的内存模型

理解Linux内核所采用的内存模型是弄懂Linux内存管理的第一步。很多介绍Linux源码阅读的书和文章都会建议新手应该从内存管理部分入手。可是,在我看来这并不是一个非常好的建议,因为如果搞不懂Linux内核中内存管理的模型直接阅读代码的话会迷失其中,一个重要原因就是这个部分很多实装方法都牵扯到了不同体系结构的差别。而Linux为了提高可移植性又对某些体系结构上普遍应用的内存模型进行了抽象。在看代码的时候,应该时刻注意区分那些是抽象了的部分,哪些代码是不同体系结构上的实现。

内存管理需要解决的问题

  • 虚拟内存管理(Virtual Memory Management)
    • 虚拟内存是现代操作系统的一个重要特征;采用虚拟内存的方法可以获得很多有点,比如通过这种抽象可以简化应用程序的开发,可以防止内存非法访问提高安全性等等;
  • 物理内存管理(Physical Memory Management)
    • 操作系统的主要功能之一就是进行资源管理,而内存恰恰就是最重要的系统资源;
  • 内核的虚拟内存管理,内核内存分配器(Allocator)
    • 应用程序或者内核内部模块需要内存时需要向内核管理模块申请,分配器帮助这些组件得到自己想要的内存;
  • 虚拟地址空间管理(Virtual Memory Space)
  • 交换(swap)和缓存(cache)
    • 交换,也是计算机系统中利用局部性(locality)特征的一个重要功能,内存管理模块可以通过交换的方式将暂时用不到的内存页“交”给低速的硬盘保存,而需要时又将这些内存内容“换”回到系统主存之中;缓存也是局部性的一个应用,现代的CPU一般都会有高速缓存,高速缓存在CPU和主存之间充当缓冲,为CPU快速得访问数据和指令提供支持。

x86结构上的地址种类

x86结构上,内存地址被分成3类,理论地址,线性地址和物理地址;

  1. 逻辑地址,是从正在运行的应用程序的角度来看,某个数据或者指令出现的位置;这个地址有可能直接就是物理地址,也有可能不是;一般来说,各种控制器,比如DMA控制器,PCI控制器对内核提出内存申请的时候所给参数都是逻辑地址;
  2. 线性地址,或者被称为平面地址空间(Flat Memory Address)的地址,事实上就是在程序员脑子里的地址,它就是从0开始每个存储单元顺序增加标号的地址。这也是最原始最简单的地址编排方式,除了Intel之外的很多CPU都采用这种地址编排方式;而Intel体系结构的CPU上采用了分段的地址空间,这种方式将线性地址按照64KB(286结构)或者4GB(386以后)为单位进行分段,而且,段地址寄存器中总是存储这当前要使用的那段内存的基址(base address)。虽然这种方式在32位结构上也可以被看作是一整个平面的地址空间,但事实上它却是分段的;
  3. 物理地址就是在总线上表示的那个地址。当物理地址和逻辑地址不一致的时候,通过内存管理单元(MMU),可以将路基地址转换为物理地址。

CPU使用内存区段单元和分页单元可以将逻辑地址转化成为物理地址;

Logical                   Linear                  Physical
Address  +--------------+ Address +-------------+ Address
-------->|Segmented Unit|-------->| Paging Unit |--------->
         +--------------+         +-------------+


参考文献
http://www.ibm.com/developerworks/jp/linux/library/l-memmod/index.html

3 thoughts on “Linux内核代码阅读序列(9)-内存模型 之一

发表评论