IA-32e架构下的内核初始化内存管理

初级内存管理单元 关于内存的分页

以往的物理页是按照4KB进行分配和管理的, 而在Linux之后流行的就是2MB大小的物理页的分配和管理, 整个物理内存管理单元也是2MB物理页管理的

先获取基本的物理地址空间信息

在bootloader程序中, 已经调用了BIOS的int 15h中断将物理内存地址的结构体放置到了1MB之下的物理地址0x7e00处, 我们需要将其提取出来

每一条物理空间信息BIOS加载到内存时20B, 因此我们要获取该数据, 也需要定义一个结构体也占用20B的物理内存大小, 获取0x7e00地址上的数据, 但是在IA-32e模式下, 我们能够使用的是线性地址, 不能直接访问物理地址, 访问物理地址需要通过我们已经在head.S程序中定义好的页表进行页的映射, 在head.S中我们只进行了10MB的映射, 这对于我们目前来说已经足够了, 不过我们还是要知道物理地址0对应的线性地址时多少, 这样我们才能进行编码

物理地址空间的大小为32个, 我们一开始先打印出这些信息, 输出物理内存哪些是可用的(type == 1), 如果多了脏数据(type > 4)证明这个地方的数据经不明数据污染了, 也就是说有数据将BIOS写到0x7e00地址上的数据覆盖了, 那我们就不要在读取了, 因为已经是错误的了, 没有意义了, 打印出来我们总共可用的内存大小

在分配可用物理页之前先获取可用物理页的页数

在这个部分, 我们需要对复制BIOS的全部物理地址空间信息到一个memory_management_struct中, 这个结构体就是我们内存管理的核心, 它保存着所有的内存页的信息, 包括不可用的

接下来我们计算出可用的物理内存页数, 获取一个可用的物理内存段之后, 我们对其起始地址尽心2MB的物理页的对齐, 返回的就是对齐后的物理地址, 接着计算出这个物理内存段的结束地址end, (end - start) >> page_2m_shift 计算出在这个物理段中有几个物理页, 也就一个分隔游戏, start就是对齐之后的物理地址, 在操作系统中一般有两个可用的物理地址段, 即为A和B, 他们一般不在一起, 第一个就是从我们的物理地址0开始的物理内存段, 显然我们的bootloader和内核代码都在这里, 这里肯定是可用的物理内存, 其实地址就是0, 对齐后的地址也是0, 因为2MB对齐就是将我们所有的内存分成一个一个的2MB, 但是另外一个可用的物理地址段它的start地址就不一定就是在一个矩形的2MB的起始位置了, 也就是说地址不对齐了, 这个时候我们就需要进行物理地址的对齐, 一般来说经过运算后, 我们原来的物理地址start的物理地址会增加一点到一个2MB的起始地址, 虽然这样会浪费一小段可用的物理地址空间, 但是我们完成了2MB的分隔, 更加方便我们的管理

分配可用物理内存页 需要用到的逻辑上的结构体

struct page --> 代表的就是我们说的2MB的物理页, 但是它本身不是2MB, 而是他管理的物理内存时2MB的, 这里所谓的管理就是通过属性保存地址, phyaddr就是管理的物理页的物理起始地址

struct zone --> 区域空间结构体, 它与page联系紧密, 它标志一个可用物理地址段, 就是我们在上面讲到了两个可用的物理地址段, 他代表着一个段, 怎么代表的呢, 也是通过属性startaddr和endaddr, startaddr保存着一个可用物理内存段的起始地址, endaddr保存着一个可用物理内存段的结束地址, 我们已经知道另一个一个物理段是很大的, 有多个2MB的物理页, 因此这里的endaddr - startadd的值也大于2MB, 所以会有多个page结构体引用着一个zone, 用来在逻辑层面上模拟分配一个页

上面已经提到过的memory_management_struct(在后面简称为mm), 他包含了从BIOS获取的物理地址信息, bitsmap(就是一个整数, 和ext3文件系统一样一样的)用来方便索引空闲的物理页page, 一个page结构体数组(在逻辑上属于zone), 一个zone结构体数组, 内核代码结束位置, 自己的结束位置,注意page和zone结构体分配在了内核代码之后, zone在page之后

开始分配可用物理内存页(类似与Python中的__new__()魔法方法的功能, 但是与Java中的new关键字的功能不同, 这里只是为page和zone结构体分配了内存, 这里到处了实质: 可用物理页的分配就是在为结构体创建内存空间, 但是不进行初始化) 初始化bitmap

mm.bits_size属性赋值为我们之前计算出来的可用物理内存页的个数, 这样才能确定bitmap的大小

将bitmap的值置为0, 虽然在这个时候我们的内核代码已经在内存中了, 我们理应将对应的bitmap中的一个位置位, 但是我们现在的内存管理的数据结构体还不完善, 所以我们将这个往后推

初始化page struct结构体数组

mm.pages_size等都记录下来, page结构体采用的4K物理页的对齐方式, 反正这些元数据结构体会比较特殊

分配内存空间, 将所有的值初始化为0

初始化zone 结构体数组

内容版权声明:除非注明,否则皆为本站原创文章。

转载注明出处:https://www.heiqu.com/zyxzfz.html