Linux内核之浅析内存管理(一)
前言
在学习linux驱动,过程中遇到一些linux内存管理上的东西,在此记录,当做回顾思考,也算作笔记以备查看,_。
一、linux内存虚拟地址布局
首先需要了解的就是在32位的linux的内存管理中,它把4G的虚拟地址空间分为了3G的用户地址空间和1G的内核地址空间。如下图所示。
下面来关注这样几个问题:
Q1:每个进程用户空间的虚拟地址空间(0-3G)是一样的,你可能会有疑问:如果进程的虚拟地址空间一样,不会造成重叠吗?
A1:答案是不会。这就涉及到虚拟地址和物理地址的概念了。CPU发出一个虚拟地址后,内存管理单元(可以想象为一个硬件部分)会根据不同的进程把这些“相同”的虚拟地址转化为(专业一点的说法是映射)不同的物理地址,所用的工具就是页表(可以看做从虚拟地址到物理地址的索引)
Q2:每个进程内核空间的虚拟地址空间(3G-4G)是一样的,那么不同的进程的内核虚拟地址不会冲突吗?
A2:答案是会。但这不影响,因为每个进程本来就是共享内核空间的,即共享3G-4G这段内核空间所对应的的物理地址空间。(准确的说,这里面的高内存段是通过不同进程的内核页表同步实现的)
二、物理地址空间的分区段
先来上一张图。
每个进程的用户空间占据着0-3G的地址空间,每个进程根据自身的页表,将要访问的地址相安无事的映射到不同的物理地址上(这里暂不考虑虚拟内存、换入换出的情况)。这种映射是动态的,即如上图中用户空间的动态映射。
相对应的,每个进程的内核虚拟地址空间是一样的(3G-4G),它们也会共享相同的内核物理地址空间(准确的说是物理内存映射区)。linux把这段共享的物理地址空间分为三个部分,如上图所示。
(1)、ZONE_DMA
(2)、ZONE_NORMAL
(3)、ZONE_HIGHMEM
其中,ZONE_DMA和ZONE_NORMAL段是直接映射的,即上图中的连续映射部分(我估计这里面主要放一些内核固定的代码部分);而
ZONE_HIGHMEM是动态映射的,其主要是为了解决1G的内核空间访问4G的物理内存的问题(vmalloc申请返回的虚拟地址就在这个部分),这里就不细说了。有兴趣的可以参照,文后的一些参考。