Linux 内核对内存的管理和使用
- 描述内存的分段和分页管理机制以及CPU多任务操作和保护方式;
- 综合说明系统中内核代码和数据以及各个任务的代码和数据在虚拟地址、线性地址和物理地址之间的对应关系;
物理内存
- 为了有效使用机器中的物理内存,在系统初始化阶段将内存划分成几个功能区域,如下图所示:
- 其中,Linux 内核程序占据物理内存的开始部分,接下来是供硬盘或软盘等块设备使用的高速缓冲区部分(其中要扣除显卡内存和 ROM BIOS 所占用的内存地址范围 640KB~1MB);
- 当一个进程需要读取块设备中的数据时,系统会首先把数据读到高速缓冲区中,当有数据需要写到块设备时,系统也是先将数据放到高速缓冲区中,然后由块设备驱动程序写到相应的设备上;
- 内存的最后部分是可供所有程序随时申请和使用的主内存区;内核程序在使用主内存区时,也同样要先向内核的内存管理模块提出申请,并在申请成功后方能使用;
- 对于含有 RAM 虚拟盘的系统,主内存区头部还要划去一部分,供虚拟盘存放数据;
- 由于计算机系统中所含的实际物理内存容量有限,因此CPU中通常都提供了内存管理机制对系统中的内存进行有效的管理;
- 在 Intel 80386 及以后的 CPU 中提供了两种内存管理(地址变换)系统:
- 内存分段系统(Segmentation System)
- 分页系统(Paging System)
- 其中分页管理系统是可选的,由系统程序员通过编程来决定是否采用;
- 为了有效地使用物理内存,Linux 系统同时采用了内存分段和分页管理机制;
内存地址空间概念
3种地址:
- 程序(进程)的虚拟和逻辑地址
- CPU的线性地址
- 实际物理内存地址
- 虚拟地址(Virtual Address)是指由程序产生的由段选择符和段内偏移地址两部分组成的地址;
- 逻辑地址(Logical Address)是指由程序产生的与段相关的偏移地址部分;
- 线性地址(Linear Address)是虚拟地址到物理地址变换之间的中间层,是处理器可寻址的内存空间中的地址;
- 物理地址(Physical Address)是指出现在CPU外部地址总线上的寻址物理内存的地址信号,是地址变换的最终结果地址;
- 虚拟内存(Virtual Memory)是指计算机呈现出要比实际拥有的内存大得多的内存容量;因此它允许程序员编制并运行比实际系统拥有的内存大得多的程序,这使得许多大型项目也能够在具有有限内存资源的系统上实现;
- 一个很恰当的比喻就是:你不需要很长的轨道就可以让一列火车从上海开到北京,你只需要足够长的铁轨(比如 3Km)就可以完成这个任务,采取的方法是把后面的铁轨立刻铺到火车的前面,只要你的操作足够快并能满足要求,列车就能像在一条完整的轨道上运行;
- 这也就是虚拟内存管理需要完成的任务,在 Linux 0.12 内核中,给每个程序(进程)都划分了总容量为 64MB 的虚拟内存空间,因此程序的逻辑地址范围是 0x00000000 ~ 0x40000000
- 综上,我们有时也把逻辑地址称为虚拟地址,因为逻辑地址和虚拟地址的概念比较类似,且与实际物理内存容量无关;
内存分段机制
- 在内存分段系统中,一个程序的逻辑地址通过分段机制自动地映射(变换)到中间层的 4GB(2^32B)线性地址空间;程序每次对内存的引用就是对内存段中内存的引用;
- 当程序引用一个内存地址时,通过把相应的段基地址加到程序员看得见的逻辑地址上,就形成了一个对应的线性地址;;
- 此时若没有启用分页机制,该线性地址就被送到CPU的外部地址总线上,用于直接寻址对应的物理内存,如下图所示:
- CPU 进行地址映射的主要目的是为了解决虚拟内存空间到物理内存空间的映射问题;
- 虚拟内存空间的含义是指一种利用二级或外部存储空间,使程序能不受实际物理内存容量限制而使用内存的一种方法;通常虚拟内存空间要比实际物理内存空间大得多;
- 那么虚拟内存管理是如何实现的呢?当一个程序引用一个不存在页面中的内存地址时,就会触发CPU产生错误异常中断;