Linux内核分析(三)
昨天我们对内核模块进行了简单的分析,今天为了让我们今后的分析没有太多障碍,我们今天先简单的分析一下linux的内存管理子系统,linux的内存管理子系统相当的庞大,所以我们今天只是初识,只要对其进行简单的了解就好了,不会去追究代码,但是在后面我们还会对内存管理子系统进行一次深度的分析。
在分析今天的内容之前,我们先来看出自的一位大神做的内存管理图,真心佩服大神。其实这张图可以分为两个部分,一部分是地址映射,另一部分就是内存分配。
所以今天我们会分析到以下内容:
1. Linux地址映射
2. Linux内存分配
l Linux地址映射
下面的分析我们依据上图进行分析,首先我们来看其最右边的地址分布图(当然这是虚拟空间)。其地址分布总的可以分为两个部分我们下面慢慢分析(基于32位处理器)。
1. 用户空间(0~3G)
a) 空间简介
其从0x00000000到0xBFFFFFFF共3GB的线性地址空间,每个进程都有一个独立的3GB用户空间,当然这是虚拟的空间。
b) 如何转换为物理空间
这一部分虚拟空间到物理空间的转换方法是我们以前在一文中分析过的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分配的是非连续的物理内存。