当前位置: 首页 > 资讯 > > 内容页

10 如何表示虚拟内存

发布时间:2023-04-27 21:26:50 来源:博客园

x86 CPU 的虚拟地址空间划分:


(资料图片)

一个应用往往拥有很大的连续地址空间,并且每个应用都是一样的,只有在运行时才能分配到真正的 物理内存,在操作系统中被称为虚拟内存;

x86CPU支持虚拟地址时要么开启保护模式要么开启长模式;保护模式下是32位,没有进行任何划分;长模式下64位,但是CPU只是实现了48位的地址空间,寄存器确实64位的,CPU用地址数据的47位扩展到最高16位,因此,要么全0、要么全1;

Cosmos 划分虚拟地址:

由以上长模式可以看出,0xFFFF800000000000~0xFFFFFFFFFFFFFFFF分给内核;0 ~ 0x00007FFFFFFFFFFF分给应用;

进一步做细分: 应用空间的最顶端是应用程序的栈,线下增长;堆是在应用程序数据区的后面,向上增长;低地址存放应用指令区和数据区;

在内核的低地址区0xFFFF800000000000~0xFFFF800400000000存放线性映射区;这是在二级引导区中建立的MMU页表映射;

设计数据结构:

虚拟地址区间、管理虚拟地址区间、对应的物理页面等;

虚拟地址区间:

虚拟地址空间往往是以区间为单位的,比如栈区、堆区、指令区、数据区;;区内部连续,区与区至之间间隔很大;当涉及到区空间的扩大时,不用建立新的虚拟地址区间数据结构,只是改变其中的指针;

kmvarsdsc_t 结构体:包含虚拟地址的开始与结束字段、自旋锁、链表、类型等;

整个虚拟地址空间:

多个虚拟地址区间连接成整个虚拟地址空间;

virmemadrs_t 结构管理了整个虚拟地址空间的区间 kmvarsdsc_t 结构体;

进程的内存地址空间:

虚拟地址空间作作用于应用程序,而应用程序在操作系统中用进程表示;一个进程由虚拟地址空间信息、进程和虚拟地址和物理地址的映射信息、应用程序文件中的指令区、数据区的开始、结束地址信息;

mmadrsdsc_t 结构体表示这些信息, 包含了mmudsc_t 表示的MMU的页表数据;

页面盒子:

每段虚拟地址区间,都会映射到对应的物理页面,根据物理内存管理器的设计,分配完页面后,会返回一个msadsc_t 结构体,所以还需要一个数据结构来挂载msadsc_t 结构体;

不把它挂载到虚拟地址区间的结构体中,出于:把一个文件映射到进程的虚拟地址空间中,只需要在内存页面保留一份共享文件,多个程序就可以共它,常规操作就是把同一物理内存页面映射到不同的虚拟地址区间,因此我们实现了一个专用的数据结构,共享操作就可以让多个 kmvarsdsc_t 结构指向它;

kvmemcbox_t 结构体实现了上述功能;可以独立存在,又和虚拟内存区间有紧密的联系,甚至可以用来管理文件数据占用的物理内存页面;

页面盒子的头:

kvmemcboxmgr_t 结构体 用来管理所有的 kvmemcbox_t 结构;

作为全局数据结构,用于找到 并 对kvmcbox_t 结构体计数;还要支持缓存多个空闲的kvmemcbox_t 结构体;

缓存是为了放置频繁分配、释放kvmemcbox_t 结构带来的系统性能抖动;同时,可以供下次取出即用,不必再找内核申请,大大提高性能;

数据结构之间的关系:

首先从进程的虚拟地址空间开始,进程的虚拟地址是 kmvarsdsc_t 结构表示,一个kmvarsdsc_t 结构表示 一个已经分配出去的虚拟地址空间;一个进程所有的 kmvarsdsc_t 结构,要交给进程的mmadrsdsc_t 结构中的 virmemadrs_t 结构管理;

为了管理虚拟地址空间对应的物理内存页面,建立了kvmembox_t 结构,由kvmemcboxmgr_t 结构统一管理,在kvmembox_t 结构中,挂载了物理内存页面对应的 msadsc_t 结构;

初始化:

虚拟地址空间的分配与释放,依赖于进程数据结构下的 mmadrsdsc_t 结构,实例一个结构变量,进行初始化;

这个在属于内核层功能;init_kvirmemadrs 函数首先调用了mmadrsdsc_t_init 函数,初始化 mmadrsdsc_t 结构;接着调用了 kvma_inituserspace_virmemadrs 函数,这个函数中建立了一个虚拟地址区间和 一个栈区间;栈区位于虚拟地址空间的顶端;

在init_krl 函数中调用init_krlmm 函数,此函数调用我们的 init_kvirmemadrs 函数;

推荐阅读