Linux高端内存
高端内存是指物理地址大于 896M 的内存. 对于这样的内存,无法在“内核直接映射空间”进行映射. 为什么? “内核直接映射空间”最多只能从 3G 到 4G,只能直接映射 1G 物理内存,对于大于 1G 的物理内存,无能为力. 实际上,“内核直接映射空间”也达不到 1G, 还得留点线性空间给“内核动态映射空间” 呢. 因此,Linux 规定“内核直接映射空间” 最多映射 896M 物理内存. 对 于高端内存,可以通过 alloc_page() 或者其它函数获得对应的 page,但是要想访问实际物理内存,还得把 page 转为线性地址才行(为什么?想想 MMU 是如何访问物理内存的),也就是说,我们需要为高端内存对应的 page 找一个线性空间,这个过程称为高端内存映射. 高端内存映射有三种方式: 1、映射到“内核动态映射空间” 这种方式很简单,通过 vmalloc() ,在”内核动态映射空间“申请内存的时候,就可能从高端内存获得页面(参看 vmalloc 的实现),因此说高端内存有可能映射到”内核动态映射空间“ 中. 2、永久内核映射 如果是通过 alloc_page() 获得了高端内存对应的 page,如何给它找个线性空间? 内核专门为此留出一块线性空间,从 PKMAP_BASE 到 FIXADDR_START ,用于映射高端内存.在 2.4 内核上,这个地址范围是 4G-8M 到 4G-4M 之间.这个空间起叫“内核永久映射空间”或者“永久内核映射空间” 这个空间和其它空间使用同样的页目录表,对于内核来说,就是 swapper_pg_dir,对普通进程来说,通过 CR3 寄存器指向. 通常情况下,这个空间是 4M 大小,因此仅仅需要一个页表即可,内核通过来 pkmap_page_table 寻找这个页表. 通过 kmap(), 可以把一个 page 映射到这个空间来 这个空间是 4M 大小,最多能同时映射 1024 个 page.因此,对于不使用的的 page,及应该时从这个空间释放掉(也就是解除映射关系),通过 kunmap() ,可以把一个 page 对应的线性地址从这个空间释放出来. 3、临时映射 内核在 FIXADDR_START 到 FIXADDR_TOP 之间保留了一些线性空间用于特殊需求.这个空间称为“固定映射空间” 在这个空间中,有一部分用于高端内存的临时映射. 这块空间具有如下特点: 1、 每个 CPU 占用一块空间 2、 在每个 CPU 占用的那块空间中,又分为多个小空间,每个小空间大小是 1 个 page,每个小空间用于一个目的,这些目的定义在 kmap_types.h 中的 km_type中. 当要进行一次临时映射的时候,需要指定映射的目的,根据映射目的,可以找到对应的小空间,然后把这个空间的地址作为映射地址.这意味着一次临时映射会导致以前的映射被覆盖. 通过 kmap_atomic() 可实现临时映射. 下图简单简单表达如何对高端内存进行映射 ------------------------- 高端内存含义为:线性地址空间 PAGE_OFFSET 896M 至4G的128M线性地址 <==映射==> 896M以上的物理页框,非直接映射.有3种方法:非连续内存区映射,永久内核映射,临时内核映射(固定映射) 从 PAGE_OFFSET开始的线性地址区域为: PAGE_OFFSET(3G)|物理内存映射 --8M-- vmalloc区 --4K-- vmalloc区 --8K-- 永久内核映射--临时内核映射(固定映射)|4G 1. 非连续区映射 1.1 每个非连续内存区都对应一个类型为 vm_struct的描述符,通过next字段,这些描述符被插入到一个vmlist链表中. 1.2 三种非连续区的类型: VM_ALLOC -- 物理内存(调用alloc_page)和线性地址同时申请,物理内存是 __GFP_HIGHMEM类型(分配顺序是HIGH, NORMAL, DMA )(可见vmalloc不仅仅可以映射__GFP_HIGHMEM页框,它的主要目的是为了将零散的,不连续的页框拼凑成连续的内核逻辑 |
凌众科技专业提供服务器租用、服务器托管、企业邮局、虚拟主机等服务,公司网站:http://www.lingzhong.cn 为了给广大客户了解更多的技术信息,本技术文章收集来源于网络,凌众科技尊重文章作者的版权,如果有涉及你的版权有必要删除你的文章,请和我们联系。以上信息与文章正文是不可分割的一部分,如果您要转载本文章,请保留以上信息,谢谢! |