一、分段机制
1、分段机制的原理图
2、段选择子
3、段偏移量
例如,我们将上面的虚拟空间分成以下 4 个段,用 0~3 来编号。每个段在段表中有一个项,在物理空间中,段的排列如下图的右边所示。
4、段表
#define GDT_ENTRY_INIT(flags, base, limit) { { { \ .a = ((limit) & 0xffff) | (((base) & 0xffff) << 16), \ .b = (((base) & 0xff0000) >> 16) | (((flags) & 0xf0ff) << 8) | \ ((limit) & 0xf0000) | ((base) & 0xff000000), \ } } }
一个段表项由段基地址 base、段界限 limit,还有一些标识符组成
DEFINE_PER_CPU_PAGE_ALIGNED(struct gdt_page, gdt_page) = { .gdt = { #ifdef CONFIG_X86_64 [GDT_ENTRY_KERNEL32_CS] = GDT_ENTRY_INIT(0xc09b, 0, 0xfffff), [GDT_ENTRY_KERNEL_CS] = GDT_ENTRY_INIT(0xa09b, 0, 0xfffff), [GDT_ENTRY_KERNEL_DS] = GDT_ENTRY_INIT(0xc093, 0, 0xfffff), [GDT_ENTRY_DEFAULT_USER32_CS] = GDT_ENTRY_INIT(0xc0fb, 0, 0xfffff), [GDT_ENTRY_DEFAULT_USER_DS] = GDT_ENTRY_INIT(0xc0f3, 0, 0xfffff), [GDT_ENTRY_DEFAULT_USER_CS] = GDT_ENTRY_INIT(0xa0fb, 0, 0xfffff), #else [GDT_ENTRY_KERNEL_CS] = GDT_ENTRY_INIT(0xc09a, 0, 0xfffff), [GDT_ENTRY_KERNEL_DS] = GDT_ENTRY_INIT(0xc092, 0, 0xfffff), [GDT_ENTRY_DEFAULT_USER_CS] = GDT_ENTRY_INIT(0xc0fa, 0, 0xfffff), [GDT_ENTRY_DEFAULT_USER_DS] = GDT_ENTRY_INIT(0xc0f2, 0, 0xfffff), ...... #endif } }; EXPORT_PER_CPU_SYMBOL_GPL(gdt_page);
5、分析
分页机制本质上来说就是类似于linux文件系统的目录管理一样,页目录项和页表项相当于根目录和上级目录,
页内便宜量就是相对路径,
绝对路径就是整个32位地址,分布式存储系统也是采用的类似的机制,先用元数据存储前面的路径,
再用块内偏移定位到具体文件,感觉道理都差不多
二、内存分页
1、物理内存
下图,举了一个简单的页表的例子,虚拟内存中的页通过页表映射为了物理内存中的页
2、虚拟地址管理
分页机制本质上来说就是类似于linux文件系统的目录管理一样,页目录项和页表项相当于根目录和上级目录,
页内变量就是相对路径,
绝对路径就是整个32位地址,分布式存储系统也是采用的类似的机制,先用元数据存储前面的路径,
再用块内偏移定位到具体文件,感觉道理都差不多
三、总结时刻
这一节我们讲了分段机制、分页机制以及从虚拟地址到物理地址的映映射方式。总结一下这两节,我们可以把内存管理系统精细化为下面三件事情:
第一:虚拟内存空间的管理,将虚拟内存分成大小相等的页;
第二:物理内存的管理,将物理内存分成大小相等的页;
第三:内存映射,将虚拟内存也和物理内存也映射起来,并且在内存紧张的时候可以换出到硬盘中。