学了很久linux内核了,但对于linux内核对于内存管理这块始终有许多疑问,学而不思则罔!看了许多书籍和博客但还是没有搞得很明白。今天仔细思考了为什么需要虚拟内存的问题,突然觉得很有收获,所以记下来和大家分享,也是为了给自己留下更深刻的印象!

1.理解进程使用的全部资源是’虚拟‘的,我们知道我们编写的应用程序最终要以进程的形式来运行,因而进程就相当于一个虚拟机(虚拟的计算机),所以我们很容易感受到自己编写的应用程序似乎使用的是所有的计算机资源,32bit的计算机我们进程似乎就是使用完整的4G内存,但是对系统稍有了解,我们就知道一个进程使用的物理内存实际可能不到几百m甚至几m!这就是一种虚拟,进程使用的是虚拟的全部计算机资源!回来再看内存,实际上使用几m的内存,但每个进程的虚拟内存却是4G!这就是虚拟内存的奥妙!虚拟内存分为用户空间和内核空间,在虚拟内存中,我们的所使用的地址是逻辑地址,例如我们现在一段代码:
#include<iostream>

using namespace std;

char strName[] = " hello world";

int main()

{

     cout<<strName<<endl;

 }

对其编译: g++ -o test   test.cpp   反汇编: objdump -h test

 

                                                                                                  


          可以看到虚拟地址空间是从0开始的布局的,所以看来我们编写的源代码,在经过编译器处理后所有的数据,代码等等地址空间都被按照从0x00000000开始定义。这下是不  是很好理解,因为如果按照物理空间地址定义,那可能完成吗?  虚拟地址空间的概念不知您充分理解没有,没有可以看看编译,链接方面的书籍。下面就是虚拟地址空间的分布问题,虚拟地址空间分为:用户空间和内核空间

                     

                                                      

在用户空间中有数据段,代码段,全局数据段等等,这个大家应该是清楚的,所以不再赘述了,我们主要分析内核空间的虚拟地址空间布局。内核地址空间有三个分类:

                              1.ZONE_DMA,包含低于16MB的内存页框

                              2.ZONE_NORMAL,包含高于16MB低于896MB的内存页框

                              3.ZONE_HIGHMEM,包含高于896MB的页框

ZONE_DMA内存区是可以直接用于DMA的内存区,而ZONE_NORMAL是一个正常的内存区域,重点是ZONE_HIGHMEM既然是1G空间为什么不将高于896MB的区域分类到

ZONE_NORMAL中呢?假如现在我们的32bit物理机有8G物理内存,那么如果按照用户3G,内核1G的分配方法,我们的应用程序不久无法使用完整的8G物理内存了吗?我们

知道进程相当于一个虚拟的物理机,我们的进程要能够使用整个计算机的资源,因此当物理机有8G物理内存时,我们的进程就应该有8G的虚拟内存!!然而我们的32bit编译

器在编译适用于32bit的应用程序时,他所编译的应用程序的虚拟地址空间只能是4G,因此为了使用另外的4G内存,我们让内核去使用另外的4G物理空间,此时我们的内核

空间就是5G啦,但是他是使用896-1024这段空间去灵活使用剩下的4G空间,具体怎么用您可以去看看相关资料。这里就不说了。


对于虚拟地址空间的分析先到这里,下一篇分析内核如何动态加载可执行文件的,然后继续写虚拟内存的映射管理。




Logo

华为开发者空间,是为全球开发者打造的专属开发空间,汇聚了华为优质开发资源及工具,致力于让每一位开发者拥有一台云主机,基于华为根生态开发、创新。

更多推荐