一步一图带你深入理解 Linux 虚拟内存管理( 十 )


内核态虚拟内存空间为 1 GB , 虚拟内存地址范围为:0xC000 000 - 0xFFFF FFFF 。

一步一图带你深入理解 Linux 虚拟内存管理

文章插图
32 位系统中用户地址空间和内核地址空间的分界线在 0xC000 000 地址处 , 那么自然进程的 mm_struct 结构中的 task_size 为 0xC000 000 。
我们来看下内核在 /arch/x86/include/asm/page_32_types.h 文件中关于 TASK_SIZE 的定义 。
/* * User space process size: 3GB (default). */#define TASK_SIZE__PAGE_OFFSET如下图所示:__PAGE_OFFSET 的值在 32 位系统下为0xC000 000 。
一步一图带你深入理解 Linux 虚拟内存管理

文章插图
而在 64 位系统中 , 只使用了其中的低 48 位来表示虚拟内存地址 。其中用户态虚拟内存空间为低 128 T , 虚拟内存地址范围为:0x0000 0000 0000 0000 - 0x0000 7FFF FFFF F000。
内核态虚拟内存空间为高 128 T , 虚拟内存地址范围为:0xFFFF 8000 0000 0000 - 0xFFFF FFFF FFFF FFFF。
一步一图带你深入理解 Linux 虚拟内存管理

文章插图
64 位系统中用户地址空间和内核地址空间的分界线在0x0000 7FFF FFFF F000 地址处 , 那么自然进程的 mm_struct 结构中的 task_size 为 0x0000 7FFF FFFF F000。
我们来看下内核在 /arch/x86/include/asm/page_64_types.h 文件中关于 TASK_SIZE 的定义 。
#define TASK_SIZE(test_thread_flag(TIF_ADDR32) ? \IA32_PAGE_OFFSET : TASK_SIZE_MAX)#define TASK_SIZE_MAXtask_size_max()#define task_size_max()((_AC(1,UL) << __VIRTUAL_MASK_SHIFT) - PAGE_SIZE)#define __VIRTUAL_MASK_SHIFT 47我们来看下在 64 位系统中内核如何来计算 TASK_SIZE , 在task_size_max() 的计算逻辑中 1 左移 47 位得到的地址是 0x0000800000000000 , 然后减去一个 PAGE_SIZE (默认为 4K) , 就是 0x00007FFFFFFFF000 , 共 128T 。所以在 64 位系统中的 TASK_SIZE 为 0x00007FFFFFFFF000。
这里我们可以看出 , 64 位虚拟内存空间的布局是和物理内存页 page 的大小有关的 , 物理内存页 page 默认大小 PAGE_SIZE 为 4K 。
PAGE_SIZE 定义在 /arch/x86/include/asm/page_types.h文件中:
/* PAGE_SHIFT determines the page size */#define PAGE_SHIFT12#define PAGE_SIZE(_AC(1,UL) << PAGE_SHIFT)而内核空间的起始地址是 0xFFFF 8000 0000 0000。在 0x00007FFFFFFFF000 - 0xFFFF 8000 0000 0000 之间的内存区域就是我们在 《4.2 64 位机器上进程虚拟内存空间分布》小节中介绍的 canonical address 空洞 。
5.2 内核如何布局进程虚拟内存空间在我们理解了内核是如何划分进程虚拟内存空间和内核虚拟内存空间之后 , 那么在 《3. 进程虚拟内存空间》小节中介绍的那些虚拟内存区域在内核中又是如何划分的呢?
接下来笔者就为大家介绍下内核是如何划分进程虚拟内存空间中的这些内存区域的 , 本小节的示例图中 , 笔者只保留了进程虚拟内存空间中的核心区域 , 方便大家理解 。
一步一图带你深入理解 Linux 虚拟内存管理

文章插图
前边我们提到 , 内核中采用了一个叫做内存描述符的 mm_struct 结构体来表示进程虚拟内存空间的全部信息 。在本小节中笔者就带大家到 mm_struct 结构体内部去寻找下相关的线索 。
struct mm_struct {unsigned long task_size;/* size of task vm space */unsigned long start_code, end_code, start_data, end_data;unsigned long start_brk, brk, start_stack;unsigned long arg_start, arg_end, env_start, env_end;unsigned long mmap_base;/* base of mmap area */unsigned long total_vm;/* Total pages mapped */unsigned long locked_vm;/* Pages that have PG_mlocked set */unsigned long pinned_vm;/* Refcount permanently increased */unsigned long data_vm;/* VM_WRITE & ~VM_SHARED & ~VM_STACK */unsigned long exec_vm;/* VM_EXEC & ~VM_WRITE & ~VM_STACK */unsigned long stack_vm;/* VM_STACK */...... 省略 ........}

经验总结扩展阅读