我们都知道,在linux的内存管理机制中,采用了虚拟内存管理机制。linux内核的虚拟地址空间共4G,分为两部分内核空间(3G~4G)以及用户空间(0~3G)。内核空间对于每个进程而言都是可见的,而用户空间对于每个用户而言是独占的,其他用户不可见。
我们都知道,程序最终是要运行在物理内存之中的,所以虽然每个进程的虚拟地址空间是一样的,但是不同的页表将会映射到不同的物理地址, 而且在同一时刻,cpu中只有一个进程再运行,因此只要在进程调度的时候装载进程的页表,就能实现虚拟内存到物理内存的映射 。 内核空间存放内核代码和数据,而用户空间存放用户代码和数据,编译之后形成的指令都是虚拟地址。物理地址是从0开始的。因此内核虚拟地址 和物理地址之间的映射只是存在一个3G的偏移量就能转换,不需要页表机制。在内核中用变量 PAGE_OFFSET: 0XC0000000,即3GB表示。 通过上面的介绍我们知道,内核通过通过线性映射只能访问1G的物理内存,这对于现在大内存的计算机来说是不实际的,因此引入了高端内存的概念,其目的在于解决映射大于1G物理内存的情况。 high_memory: 这个变量的字面含义是高端内存,到底什么是高端内存, Linux内核规定,RAM的前896为所谓的低端内存, 而896~1GB共128MB为高端内存。如果你的内存是512M,那么high_memory是多少? 是3GB+512M,也就是说,物理地址x<=896M,就有内核地址0xc0000000+x,否则,high_memory=0xc0000000+896M 或者说high_memory实际值为0xc0000000+x,但最大不能超过0xc0000000+896M(因为直接的地址映射最大只能达到896M) 在源代码中函数mem_init中,有这样一行: high_memory = (void *) __va(max_low_pfn * PAGE_SIZE); 其中,max_low_pfn为物理内存的最大页数。 所以,PAGE_OFFSET到high_memory 之间就是所谓的物理内存映射。只有这一段之间物理地址与虚地址之间是简单的线性关系。 还要说明的是,要在这段内存分配内存,则调用kmalloc()函数。反过来说,通过kmalloc()分配的内存,其物理页是连续的。 vmalloc()与 kmalloc()都是在内核代码中用来分配内存的函数,但二者有何区别? 从前面的介绍已经看出,这两个函数所分配的内存都处于内核空间,即从3GB~4GB;但位置不同,kmalloc()分配的内存处于3GB~high_memory之间,这一段内核空间与物理内存的映射一一对应,而vmalloc()分配的内存在VMALLOC_START~4GB之间,这一段非连续内存区映射到物理内存也可能是非连续的。 (责任编辑:IT) |