17 | 划分土地(中):如何实现内存页面初始化?
LMOS
该思维导图由 AI 生成,仅供参考
你好,我是 LMOS。
上节课,我们确定了用分页方式管理内存,并且一起动手设计了表示内存页、内存区相关的内存管理数据结构。不过,虽然内存管理相关的数据结构已经定义好了,但是我们还没有在内存中建立对应的实例变量。
我们都知道,在代码中实际操作的数据结构必须在内存中有相应的变量,这节课我们就去建立对应的实例变量,并初始化它们。
初始化
前面的课里,我们在 hal 层初始化中,初始化了从二级引导器中获取的内存布局信息,也就是那个 e820map_t 数组,并把这个数组转换成了 phymmarge_t 结构数组,还对它做了排序。
但是,我们 Cosmos 物理内存管理器剩下的部分还没有完成初始化,下面我们就去实现它。
Cosmos 的物理内存管理器,我们依然要放在 Cosmos 的 hal 层。
因为物理内存还和硬件平台相关,所以我们要在 cosmos/hal/x86/ 目录下建立一个 memmgrinit.c 文件,在这个文件中写入一个 Cosmos 物理内存管理器初始化的大总管——init_memmgr 函数,并在 init_halmm 函数中调用它,代码如下所示。
根据前面我们对内存管理相关数据结构的设计,你应该不难想到,在 init_memmgr 函数中应该要完成内存页结构 msadsc_t 和内存区结构 memarea_t 的初始化,下面就分别搞定这两件事。
公开
同步至部落
取消
完成
0/2000
荧光笔
直线
曲线
笔记
复制
AI
- 深入了解
- 翻译
- 解释
- 总结
本文深入介绍了在内存中实现内存页面初始化的过程,以及解决内存占用问题的重要性。作者首先确定了使用分页方式管理内存,并设计了表示内存页、内存区相关的内存管理数据结构。在Cosmos物理内存管理器中完成初始化的过程中,作者详细介绍了从二级引导器中获取内存布局信息并转换成phymmarge_t结构数组的排序过程。文章还详细介绍了内存页结构的初始化过程,包括如何找到可用的内存地址,扫描phymmarge_t结构体数组中的信息,并建立一个msadsc_t结构体数组。通过详细的步骤和代码示例,读者可以了解如何在内存中实现内存页面初始化,并解决内存占用问题。 此外,文章还介绍了解决内存占用问题的重要性,以及如何标记已被占用的内存页面所对应的msadsc_t结构,以避免内存分配算法错误地分配已被占用的内存页。通过详细的步骤和代码示例,读者可以了解如何在内存中实现内存页面初始化,并解决内存占用问题。 总的来说,本文是一篇技术性较强的文章,通过详细的步骤和代码示例,帮助读者了解了如何在内存中实现内存页面初始化,以及解决内存占用问题。文章内容涉及内存管理数据结构设计、内存页结构初始化、解决内存占用问题的重要性等方面,对于从事系统开发和内存管理的技术人员具有一定的参考价值。
仅可试看部分内容,如需阅读全部内容,请付费购买文章所属专栏
《操作系统实战 45 讲》,新⼈⾸单¥68
《操作系统实战 45 讲》,新⼈⾸单¥68
立即购买
© 版权归极客邦科技所有,未经许可不得传播售卖。 页面已增加防盗追踪,如有侵权极客邦将依法追究其法律责任。
登录 后留言
全部留言(27)
- 最新
- 精选
- neohope一、稍微整理了一下流程: init_hal->init_halmm->init_memmgr //每个页对应一个msadsc_t 结构体,循环填充msadsc_t 结构体数组 ->init_msadsc //初始化三类memarea_t,硬件区、内核区、用户区 ->init_memarea //对已使用的页打上标记,包括:BIOS中断表、内核栈、内核、内核映像 ->init_search_krloccupymm(&kmachbsp); //将页面按地址范围,分配给内存区 //然后按顺序依次查找最长连续的页面,根据连续页面的长度, //将这些页面的msadsc_t挂载到memdivmer_t 结构下的bafhlst_t数组dm_mdmlielst中 ->init_merlove_mem(); //物理地址转为虚拟地址,便于以后使用 ->init_memmgrob(); 二、对于最后的问题,用了虚拟机进行测试,但无论内存大小,总有56K内存没能找到【有知道的小伙伴,麻烦帮忙解答一下】: 1、4G内存情况如下: 理论内存:0x1 0000 0000 = 4,194,304K 可用内存:0xfff8fc00 = 4,193,855K 预留区域:0x52400 = 329K 硬件使用:0x10000 = 64K 没能找到:0xE000 = 56K msadsc_t结构体大小为40,使用内存总计为: 4,193,855K/4K*40=41,938,520=接近40M 2、2G内存情况如下 理论内存:0x8000 0000 =2,097,152K 可用内存:0x7ff8fc00 = 2,096,703K 预留区域:0x52400 = 329K 硬件使用:0x10000 = 64K 没能找到:0xE000 = 56K msadsc_t结构体大小为40,使用内存总计为: 2,096,703K/4K*40=20,967,030=接近20M 3、1G内存情况如下 理论内存:0x4000 0000= 1,048,576K 可用内存:0x3ff8fc00 = 1,048,127K 预留区域:0x52400 = 329K 硬件使用:0x10000 = 64K 没能找到:0xE000 = 56K msadsc_t结构体大小为40,使用内存总计为: 1,048,127K/4K*40=10,481,270=接近10M 三、如果想节约msadsc_t内存的话,感觉有几种方案: 1、最简单的方法,就是大内存时采用更大的分页,但应用在申请内存时,同样会有更多内存浪费 2、也可以用更复杂的页面管理机制,比如相同属性的连续页面不要用多个单独msadsc_t表示,而用一个msadsc_t表示并标明其范围,并通过skiplist等数据结构加速查询。但无论是申请内存还是归还内存时,性能会有所下降,感觉得不偿失。 3、页面分组情况较少的时候,可以通过每个组建立一个链表记录哪些页面属于某个链表,而msadsc_t中只记录地址等少量信息,不适合复杂系统。
作者回复: 大神 6666
2021-06-17526 - 黄光华老师,我觉得这个类、变量的命名可读性,还是非常非常重要的 这个项目是您手写的,每一个命名什么意思,你了然于胸 但是我们都是新手,很多变量命名真的太简略了,有很多命名就算琢磨也不一定能知道是什么意思。 真心建议命名可读性还是要增强一下哈~~
作者回复: 好的
2021-09-0225 - 小李飞刀大佬的这个变量命名是真的把我看懵了。。。
作者回复: 哈哈
2022-06-252 - 朱炜敏老师,初始化这些数据结构的过程跟行为,让我想到了自己在电脑上装上4G内存条后,上电后发现系统反馈的可用内存一般只有3.8G左右。 是不是类似的,消失的几百兆内存里,存放的就是这些页管理的数据结构?
作者回复: 还有内核 的其它数据 但32位下 只能使用2.8GB
2021-11-042 - pedro胡乱一猜~ msadsc_t 占用内存 = 4GB/4KB(页大小) * sizeof(msadsc_t )
作者回复: 是的
2021-06-1632 - 秋宇雨u1s1,代码命名真心看晕了
编辑回复: 攻略:关注下这些代码要实现的功能是啥。还是死磕不出来的展开说说,大家一起讨论解决。
2022-01-281 - 浮生尽歇怎么调试内核呢?
作者回复: KPrint
2021-11-141 - 杨军这一讲的内容、概念很多,尤其是内存页合并到内存区的代码不好理解,建议大家把16讲的内存页面组织结构图放在手边,对照代码多看几次慢慢就有感觉了,加油,过了内存管理这道坎,就看见胜利的曙光了
作者回复: 哈哈
2021-09-191 - Geek_a5edac代码的命名,不太好懂,能说下命名规则么,一些看很久才知道是哪些缩写
作者回复: 不需要搞懂的,不要陷入名词概念之中
2021-07-241 - 求助一下可能是编译或者是链接方面的问题。不知道为什么全局变量被定义到了很远的位置。比如kernel.bin的大小只有56512Byte。地址从0x2000000开始。所以我设定mb_nextwtpadr的初始值为0x200e000。但是全局变量的地址却被定义在了0x220e000。这样导致了用mb_nextwtpadr向后申请内存的最终会覆盖掉全局变量的数据。想知道gcc或者ld的什么参数可以改变全局变量所在的位置啊?
作者回复: 看看链接器脚本 data 和 bss 的位置
2022-12-06归属地:湖北2
收起评论