昨天我们对内核模块进行了简单的分析,今天为了让我们今后的分析没有太多障碍,我们今天先简单的分析一下linux的内存管理子系统,linux的内存管理子系统相当的庞大,所以我们今天只是初识,只要对其进行简单的了解就好了,不会去追究代码,但是在后面我们还会对内存管理子系统进行一次深度的分析。
在分析今天的内容之前,我们先来看出自http://bbs.chinaunix.net/thread-2018659-2-1.html的一位大神做的内存管理图,真心佩服大神。其实这张图可以分为两个部分,一部分是地址映射,另一部分就是内存分配。
所以今天我们会分析到以下内容:
1. Linux地址映射
2. Linux内存分配
下面的分析我们依据上图进行分析,首先我们来看其最右边的地址分布图(当然这是虚拟空间)。其地址分布总的可以分为两个部分我们下面慢慢分析(基于32位处理器)。
1. 用户空间(0~3G)
a) 空间简介
其从0x00000000到0xBFFFFFFF共3GB的线性地址空间,每个进程都有一个独立的3GB用户空间,当然这是虚拟的空间。
b) 如何转换为物理空间
这一部分虚拟空间到物理空间的转换方法是我们以前在http://www.cnblogs.com/wrjvszq/p/4246634.html一文中分析过的MMU地址转换。
2. 内核空间(3~4G)
其从0xC0000000到0xFFFFFFFF共1GB大小,内核空间又可以根据映射方式的不同分为下面四块,我们一一分析
a) 内核逻辑地址空间
l 空间简介
其从0xC0000000到high_memory(图中896MB的地方)最大为896MB(也就是说这块空间有可能不满,但最大为896MB),当然是虚拟空间。
注:在此注意一下896MB我们一会在分析。
l 如何转换为物理空间
这一部分虚拟地址与物理内存中对应的地址只差一个固定偏移量(3G),如果内存物理地址空间从0x00000000地址编址,那么这个固定偏移量就是PAGE_OFFSET(如上图)。
b) Vmalloc空间
l 空间简介
其地址没有严格的界限,这段空间既可以访问到我们的高端内存,也可以访问到低端内存。(高端和低端一会解释)
l 如何转换为物理空间
不是通过简单的线性关系映射,在此不研究。
c) 永久内核映射
l 空间简介
其固定用来访问高端内存。
l 如何转换为物理空间
不是通过简单的线性关系映射,在此不研究。
d) 固定映射
l 空间简介
其在系统初始化期间永久映射I/O地址空间,或者特殊的寄存器。
3. 遗留知识
在刚才我们前面的分析中我们留下了一些问题下面进行解释。
a) 低端内存
内核逻辑地址空间所映射的物理内存就是低端内存(实际物理内存的大小,但是小于896MB)
b) 高端内存
低端内存地址之上的物理内存是高端内存(物理内存896MB之上)。
c) 896MB来由
Linux将内存分为内核空间和用户空间,其中内核空间中的0xC0000000~high_memory部分用来映射物理内存,但是我们还需要映射I/O空间和固定的寄存器,所以留出了high_memory~0xFFFFFFFF之间的地址来映射I/O空间和固定的寄存器,而在X86平台根据经验设定了这个high_memory为896MB。
l Linux内存分配
通过上面的介绍我们对linux对内存的管理,以及地址的映射有了一个了解,下面我们来分析linux是如何进行内存分配的。
通过上图我们可以分析出内存的分配过程
1. 由malloc、fork等系统调用和kmalloc、vmalloc申请得到虚拟内存。
2. 在我们使用该内存的时候,产生请页异常(kmalloc除外)
3. 从空闲的页框分配物理内存,和虚拟地址建立映射。
注:kmalloc申请空间是不用经过请页异常的,返回的虚拟地址已经对应了物理内存。Kmalloc可以分配到连续的物理内存,vmalloc分配的是非连续的物理内存。