Linux内核高端内存理解划分

Linux内核高端内存理解划分

例如内核想访问2g开始的一段大小为1mb的物理内存,即物理地址范围为0x80000000 ~ 0x800fffff。访问之前先找到一段1mb大小的空闲地址空间,假设找到的空闲地址空间为0xf8700000 ~ 0xf87fffff,用这1mb的逻辑地址空间映射到物理地址空间0x80000000 ~ 0x800fffff的内存。

映射关系如下:

Linux内核高端内存理解划分

linux内核高端内存的划分内核将高端内存划分为3部分:vmalloc_startvmalloc_end、kmap_basefixaddr_start和fixaddr_start~4g。

Linux内核高端内存理解划分

对于高端内存,可以通过 alloc_page() 或者其它函数获得对应的 page,但是要想访问实际物理内存,还得把 page 转为线性地址才行(为什么?想想 mmu 是如何访问物理内存的),也就是说,我们需要为高端内存对应的 page 找一个线性空间,这个过程称为高端内存映射。

对应高端内存的3部分,高端内存映射有三种方式:映射到”内核动态映射空间”(noncontiguous memory allocation)这种方式很简单,因为通过 vmalloc() ,在”内核动态映射空间”申请内存的时候,就可能从高端内存获得页面(参看 vmalloc 的实现),因此说高端内存有可能映射到”内核动态映射空间”中。持久内核映射(permanent kernel mapping)如果是通过 alloc_page() 获得了高端内存对应的 page,如何给它找个线性空间? 内核专门为此留出一块线性空间,从 pkmap_base 到 fixaddr_start ,用于映射高端内存。在 2.6内核上,这个地址范围是 4g-8m 到 4g-4m 之间。这个空间起叫”内核永久映射空间”或者”永久内核映射空间”。这个空间和其它空间使用同样的页目录表,对于内核来说,就是 swapper_pg_dir,对普通进程来说,通过 cr3 寄存器指向。通常情况下,这个空间是 4m 大小,因此仅仅需要一个页表即可,内核通过来 pkmap_page_table 寻找这个页表。通过 kmap(),可以把一个 page 映射到这个空间来。由于这个空间是 4m 大小,最多能同时映射 1024 个 page。因此,对于不使用的的 page,及应该时从这个空间释放掉(也就是解除映射关系),通过 kunmap() ,可以把一个 page 对应的线性地址从这个空间释放出来。临时映射(temporary kernel mapping)内核在 fixaddr_start 到 fixaddr_top 之间保留了一些线性空间用于特殊需求。这个空间称为”固定映射空间”在这个空间中,有一部分用于高端内存的临时映射。

段页式机制如下图。

Linux内核高端内存理解划分

linux内核地址空间划分通常32位linux内核地址空间划分03g为用户空间,34g为内核空间。注意这里是32位内核地址空间划分,

Linux内核高端内存理解划分

64位内核地址空间划分是不同的。

linux内核高端内存的由来

当内核模块代码或线程访问内存时,代码中的内存地址都为逻辑地址,而对应到真正的物理内存地址,需要地址一对一的映射,如逻辑地址0xc0000003对应的物理地址为0x3,0xc0000004对

Linux内核高端内存理解划分

zone_dma 内存开始的16mb

zone_normal 16mb~896mb

zone_highmem 896mb ~ 结束(linux内核 )

  • Linux内核高端内存理解划分已关闭评论
    A+
发布日期:2019年07月03日  所属分类:新闻动态