linux 内核4.8版本以上 内存管理具体源码解析

linux 4.8 版本  内核 内存管理源码解析  2018年06月21日 14:18:44 ( 紧跟最新linux ,会动态持续更新)

关于服务器体系和 共享存储 可 参见  服务器体系(SMP, NUMA, MPP)与共享存储器架构(UMA和NUMA) 文章。

本文实际验证环境如下:2台unbuntu14系统,一台客户测试虚拟机、虚拟内存1G,一台目标内核测试虚拟机。linux4.8版本,调试工具位源码级kgdb 调试、具体的环境搭配省略、如遇到问题,可联系我。

在网上大多讨论 32位的版本,而没有对64位系统 进行对照的描述,以至于描述的不清不楚,对读者造成误解。其实 64位和32位的 内存管理是 差别很大的, 64位系统由于线性地址大 、就没有所谓的高端内存。

1.linux 32位 和 64位 内存管理是完全不同的,在Linux内部的地址的映射过程为逻辑地址–>线性地址–>物理地址 。32位的内存计算如下 :

linux 内核4.8版本以上 内存管理具体源码解析_第1张图片
图-1(32位)

而64位系统的地址计算如下:

linux 内核4.8版本以上 内存管理具体源码解析_第2张图片
图-2(64位)

在没有物理地址扩展的32位系统,两级页表已经足够了,linux 通过使 “页上级目录” 和“ 页中间目录” 位全为 0 ,从根本上取消了页上级目录和页中间目录字段。不过,页上级目录和页中间目录在指针序列中的位置被保留,以便同样的代码在32位系统和64位系统下都能使用。内核为页上级目录和 页中间目录保留了一个位置,这是通过把他们的页目录项数设置为1 ,并把这两个目录项映射到页全局目录的一个适当的目录项而实现的。

我们只要搞懂kmalloc 、vmalloc 函数的具体实现,基本就可以掌握Linux内核的内存管理。现在让我们分析一些 vmalloc 的源码具体的了解 linux 最新 内核 的内存管理、本文以 64位系统为例,32位的本文暂时不提。

系统首先初始化物理内存, 如何初始化呢 ?  

从start_kernel函数开始, 初始化内存结点, 

 

#define NODE_DATA(id)  (&contig_page_data)    //UMA 系统只有一个伪结点。

64位linux vmalloc 可以分配多大的内存呢 ?

让我们执行以下命令(在目标机或者客户机上都可、一样的结果) : cat /proc/meminfo

其中有一个MemTotal和MemFree

MemTotal表示所有内存, MemFree表示可分配内存。 如图MemTotal共 998744KB (975M)、可用内存189364KB(185M)实际分配虚拟机1024M.  vmalloctotal = 34359738367KB = 32768G 内存可用。

linux 内核4.8版本以上 内存管理具体源码解析_第3张图片

1.首先在vmalloc.c 文件的vmalloc 函数打上断点  ,使用命令在gdb 调试工具下:   b  vmalloc即可

并列出 vmalloc 函数的源代码 1742 -  1744 行。

linux 内核4.8版本以上 内存管理具体源码解析_第4张图片

让我们进入 vmalloc 函数的下层函数 __vmalloc_node_flag () 内部,看一下。参数 为 在 GFP_KERNEL|__GFP_HIGHMEM 中 分配内存(在高端内存不足时,用低端内存)

linux 内核4.8版本以上 内存管理具体源码解析_第5张图片

那么 让我们打印出 vmalloc范围内存的起始值 如下 :  __vmalloc_node_rang 中 高端内存VMALLOC_START(0xffff c900 0000 0000) 、 低端内存VMALLOC_END(0xffff e8ff ffff ffff)、两者相差: 0x1fff ffff ffff(11个f)  让我们在文件中查一下 验证: 在文件中 pgtable_64_types.h中定义

# define VMALLOC_START vmalloc_base  而 这个参数 在 head64.c 中 查看到 是下面的 语句。

unsigned long vmalloc_base __ro_after_init = __VMALLOC_BASE_L4; 这个常量 就是 具体的数字。

32位系统划分如下 :  1G 的 内核空间 (0xc000 0000  ~ 0xffff ffff  ) ,   3G 的用户线性空间。

    内核空间具体划分为  page_offset (0xc000 0000) 到 high_memory , 8M  的间隔 ,  vmalloc_start     --->   vmalloc_end   ,  PKMAP_BASE  ,  FIXADDR_START ,  0xffff ffff 线性截至。

64位划分如下 :   内核空间0xffff 8000 0000 0000  ->  0xffff ffff ffff ffff  (比特位 【0,46】任意,[47,63]全1)

用户区0x0000 7ffff  ffff  ffff  ->  0   (比特位 【0,46】 任意 , 【47,63 】全 1 ) ,上半部内核区 和  下半部 用户区 ,中间存在 非规范区。

你可能感兴趣的:(linux 内核4.8版本以上 内存管理具体源码解析)