23.12.4.-8
linux内存系统可以从物理内存、物理地址空间、虚拟地址空间三个概念来考虑。物理内存是物理地址空间的一部分。
首先明确内存访问过程,程序中使用的都是虚拟地址,所有的内存访问从软件角度都是虚拟地址。同时,真实的存储都是在物理内存或者外设寄存器上,这些物理内存和外设寄存器在物理地址空间上的分配一同构成了物理内存布局。只有虚拟地址正确地匹配到这张物理内存布局图上,整个访问过程才能得以正确地进行。
因此,进行内存管理,实际上就是:
- 在需要虚拟内存时,能够知道哪些虚拟内存不能使用,哪些还可以分配出去;
- 在需要物理内存时,能够知道哪些物理内存不能使用,哪些还可以分配出去;
- 在适当的时候将虚拟内存通过页表映射的物理内存上去。
任何内存管理手段,前两个问题是核心,实际上都是在回答这两个核心问题。在解决这两个核心问题后,可以进行一些锦上添花的操作,例如可以在实际写内存时才分配物理内存,提升物理内存的实际利用率等等。
这两个问题,在逻辑上是两个完全独立的问题,虚拟内存的分配可以和物理内存分配没有任何关系,让二者关联的方式就是地址映射,也就是通过页表将虚拟地址转换成物理地址。
因此,对于任何一个内核代码中的内存申请,在逻辑上都可以分成三步:
- 在虚拟空间中申请对应的虚拟内存地址范围(虚拟分配器);
- 在物理内存中申请对应的内存块(物理分配器);
- 通过页表完成二者的映射。
这里有两个容易产生牛角尖的问题需要提前回答。
- 否每次动态申请虚拟内存都需要动态申请物理内存呢?
答:不是。有些物理内存的地址是确定好的,当电路设计好之后就确定了,例如很多外设寄存器,当物理连线结束后,就只能通过对应的物理地址才能访问。因此对待这种类型的申请,就不需要动态分配物理内存,只需要找到合适的虚拟地址空间,分配给这段物理内存即可。 - 是否动态分配物理内存后,一定要动态申请一次虚拟内存?
答:不是。对于所谓的低端物理内存,其于虚拟地址空间的映射关系是固定的,即只差一个固定的偏移值。这种情况下,分配物理内存的同时也相当于分配了虚拟内存,反之亦然。
接下来将按照物理分配器、虚拟分配器的思路进行逐一分析。