一、实验目的

实验二主要涉及操作系统的物理内存管理。操作系统为了使用内存,还需高效地管理内存资源。在实验二中大家会了解并且自己动手完成一个简单的物理内存管理系统。

  • 理解基于段页式内存地址的转换机制
  • 理解页表的建立和使用方法
  • 理解物理内存的管理方法

二、实验内容

本次实验包含三个部分。首先了解如何发现系统中的物理内存;然后了解如何建立对物理内存的初步管理,即了解连续物理内存管理;最后了解页表相关的操作,即如何建立页表来实现虚拟内存到物理内存之间的映射,对段页式内存管理机制有一个比较全面的了解。本实验里面实现的内存管理还是非常基本的,并没有涉及到对实际机器的优化,比如针对 cache 的优化等。如果大家有余力,尝试完成扩展练习。

三、实验练习

1.练习0:填写已有实验
将Lab1中完成的代码复制到Lab2中,涉及到的文件为kern/debug/kdebug.c和kern/trap/trap.c。

2.练习1:实现first-fit连续物理内存分配算法(需要编程)
在实现first fit内存分配算法的回收函数时,要考虑地址连续的空间块之间的合并操作。提示:在建立空闲页块链表时,需要按照空闲页块起始地址来排序,形成一个有序的链表。可能会修改default_pmm.c中的default_init,default_init_menmmap,default_alloc_pages,default_free_pages等相关函数。请仔细查看和理解default_pmm.c中的注释。

① 设计实现过程
a.first-fit算法基本思想:
物理内存管理器顺着双向链表进行搜索空闲区域内存区域,直到找到一个足够大的空间,如果空间大小和申请分配的大小相等,则直接把这个空闲区域分配出去;如果空间大于申请分配的空间大小,则将此区域分为两部分,一部分分配出去,另一部分留下形成一个新的空闲区。
释放内存通过将区域重新放回空闲列表中即可。

b.实现first-fit连续物理内存分配算法的实现过程:
ucore采用面对对象编程的思想,将物理内存管理的内容抽象成若干个特定的函数,并使用结构体pmm_manager来将这些函数的指针封装起来,当具体使用物理内存管理功能时,调用已经初始化完成的pmm_manager的实例中的函数指针即可。通过这种抽象来实现将物理内存管理的具体实现与ucore其他部分分隔开来的效果。pmm_manager中提供的物理内存管理函数如下:

  • default_init:对物理内存管理器的初始化。可以初始化free_列表,并将nr_free设置为0.

  • default_init_memmap:对管理的空闲页的数据进行初始化。调用map:kern_init–>pmm_init–>page_init–>init_memmap–>pmm_manager->init_memmap

  • p->flags应设置为bit PG_属性,表示此页有效。

  • 保留的位PG_在p->flags中设置。

  • 如果此页是空闲的,并且不是空闲块的第一页,则p->property应设置为0

  • 如果此页是空闲的,并且是空闲块的第一页,则p->property应设置为所有块的页数

  • p现在是空闲的,则p->ref为0

  • 可以使用p->page_link来将此页面链接到free_list(空闲列表)中(例如:list add before(&free list,&(p->page link));)

  • 最后,可以求空闲块的总数:nr_free += n

  • default_alloc_pages:申请分配指定数量的物理页。在空闲列表中搜索并找到第一个空闲块(块大小>=n),然后重新划分空闲块,返回地址。

  • default_free_pages:申请释放若干指定物理页。将页面重新链接到空闲列表,可能会将小的空闲块合并到大的空闲块中。

  • default_nr_free_pages:查询当前的空闲页总数

  • default_check:对物理内存管理器进行测试

c.default_pmm.c文件可以看出,最终ucore中所使用的物理内存管理器中的函数指针分别指向了default_init,default_init_memmap等函数,可以通过修改这些函数,来实现对first-fit连续内存分配算法。

d.函数修改:

  • default_init函数:对空闲内存块链表进行初始化,并将总空闲数目置零,与具体物理内存分配算法无关,不进行修改。
  • default_init_memmap函数:对最初的一整块未被占用的物理内存空间中的每一页所对应的page结构(状态)进行初始化。相邻物理页对应的page结构在内存上也是相邻的,因此可以直接通过第一个空闲物理页对应的page结构加上一个偏移量的方式,来访问所有的空闲的物理页的page结构。具体初始化方式:
    遍历所有空闲物理页的page结构,将page结构中描述空闲块数目的变量置零(故该成员变量只有在整个空闲块的第一个page中才有意义),然后清空这些物理页的引用计数,再通过设置flags的位的方式将其标记为空闲。

    再对空闲块的第一个页的page结构进行初始化,具体实现为,将其表示空闲块大小的成员变量设置为参数环路的空闲块大小(单位为页),然后更新存储所有空闲页数量的全局变量,再将这个空闲块插入到空闲内存块链表中(只需将第一个page的page_link插入即可)。
  • default_alloc_pages:分配指定页数的连续空闲物理空间,并将第一页的page结构的指针作为结果返回。具体实现方式:
    对参数进行合法性检查,并查询总的空闲物理页数目是否足够进行分配。如果不足够进行分配,直接返回NULL,分配失败。
    从头开始遍历保存空闲物理内存块的链表(按照物理地址从小到大的顺序),如果找到一个连续内存块的大小满足当前需要的内存块,则说明可以成功匹配。优先选择第一个遇到的满足条件的空闲内存块来完成内存分配。代码实现如下:

    如果内存块的大小大于需要的内存大小,则将空闲内存块分裂为两块,一块大小为所需内存大小,另一块则重新进行初始化。重新初始化包括对第一个page中表示空闲块代销的成员变量进行设置,其应当设置为剩下的空闲块大小,并将这个分裂出来的空闲块插入到空闲块链表中(链表中的空闲块按照物理地址从小到大排序)。如果内存块大小与所需大小相同,则不用分裂,对分配出去的物理内存的每一个描述信息(对应的page结构)进行初始化,修改flags成员变量,设置成非空闲,再将原始空闲块在空闲链表中删除,更新表示总空闲页数量的全局变量;最后返回用于分配到的物理内存的page结构指针。代码如下:
  • default_free_pages:释放指定的某一物理页开始的连续物理页,并且完成first-fit算法中需要的一些信息维护。具体实现如下:
    考虑遍历需要释放的物理页的page结构,对其进行更新。更新方式:
    1.判断原先这些物理页是否被占用,如果释放未被占用的物理页,说明出现异常
    2.设置flags将这些物理页标记为空闲
    3.清空这些物理页的引用计数

    4.将这一新的空闲块插入到空闲块链表中

    5.对空闲块跟其相邻的空闲块合并。通过merge_backward函数实现,将指定的某一个空闲块与其链表后的空闲块进行合并,如果合并失败返回0,否则返回1.

    6.merge_backward函数:
  • first-fit算法实现至此基本完成。
    ② 回答问题:你的first-fit算法是否有进一步的改进空间
    答:
    有的。最主要的不足在时间效率。每次要查询一块适合条件的空闲内存块时,需要对链表进行遍历。最坏的情况需要找遍整个链表,时间复杂度为O(n),n为当前链表大小。
    改进方法:采取树的结构来取代简单的链表结构,按照中序遍历把得到的空闲块序列的物理地址按照从小到大的顺序排列。时间复杂度可以从O(n)提升到O(log n)

3.练习2:实现寻找虚拟地址对应的页表项(需要编程)
通过设置页表和对应的页表项,可建立虚拟内存地址和物理内存地址的对应关系。其中的get_pte函数是设置页表项环节中的一个重要步骤。此函数找到一个虚地址对应的二级页表项的内核虚地址,如果此二级页表项不存在,则分配一个包含此项的二级页表。本练习需要补全kern.mm/pmm.c中的get_pte函数,实现其功能。请仔细查看和理解get_pte函数中的注释。get_pte函数的调用关系图如下所示:

① 设计实现过程

  • get_pte函数:根据给定的页目录项page directory以及线性地址,查询出该linear address对应的页表page table entry,并且根据输入参数要求判断是否需要创建不存在的页表。代码实现:

    ② 回答如下问题:
    a.请描述页目录项(Page Director Entry)和页表(Page Table Entry)中每个组成部分的含义和以及对ucore而言的潜在用处。
    答:

  • 页目录项PDE的每个组成部分如下:
    前20位表示4K对齐的该PDE对应的页表起始位置(物理地址,该物理地址的高20位即PDE中的高20位,低12位为0)
    第9-11位未被CPU使用,可保留给OS使用
    第8位可忽略;
    第7位用于设置Page大小,0表示4KB;
    第6位恒为0;
    第5位用于表示该页是否被使用过;
    第4位设置为1,表示不对该页进行缓存;
    第3位是否使用write through缓存写策略;
    第2位表示该页的访问需要的特权级;
    第1位表示是否允许读写;
    第0位为该PDE的存在位。

  • 页表项PTE中的诶个组成部分含义:
    高20位与PDE相似,用于表示该PTE指向的物理页的物理地址;
    第9-11位保留给OS使用;
    第7-8位恒为0;
    第6位表示该页是否为dirty,即是否需要在swap out的时候写回外存;
    第5位表示是否被访问;
    第3-4位恒为0
    第2位表示访问该页需要的特权级;
    第1位表示是否允许读写;
    第0位表示存在位。

    b.如果ucore执行过程中访问内存,出现了页访问异常,请问硬件要做哪些事情?
    答:
    1)将发生错误的线性地址保存在cr2寄存器中
    2)在中断栈中依次压入EFLAGS,CS,EIP,以及页访问异常码error code,如果page fault是发生在用户态,则还需要先压入ss和esp,并且切换到内核栈;
    3)根据中断描述符表查询到对应page fault的ISR,跳转到对应的ISR处执行,接下来将由软件进行page fault处理。

4.练习3:释放某虚地址所在的页并取消对应二级页表项的映射(需要编程)
当释放一个包含某虚地址的物理内存页时,需要让对应此物理内存页的管理数据结构Page做相关的清除处理,使得此物理内存页成为空闲;另外还需要把表示虚地址与物理地址对应关系的二级页表项清除。请仔细查看和理解page_remove_pte函数中的注释。补全在kern/mm/pmm.c中的page_remove_pte函数。page_remove_pte函数的调用关系如下图所示:

① 设计实现过程
确保传入的二级页表项是存在的,再获取页表项对应物理页的page结构;
减少该物理页的引用计数,如果该物理页的引用计数变为0,说明不存在任何虚拟页指向该物理页,对该物理页进行释放;
将PTE的存在位设为0,清除该映射关系;
刷新TLB表,确保TLB中的缓存不会有错误的映射关系
代码实现如下:

② 回答如下问题:
a.数据结构page的全局变量(其实是一个数组)的每一项与页表中的页目录项和页表项有无对应关系?如果有,其对应关系是什么?
答:
存在对应关系。由于页表项中存放着对应的物理页的物理地址,因此可以通过这个物理地址来获取到对应的page数组的对应项。具体做法为,将物理地址除以一个页的大小,然后乘上一个page结构的大小获得偏移量,再使用page数组的基址加上偏移量,可以得到对应的page项地址。

b.如果希望虚拟地址与物理地址相等,则需要如何修改lab完成?
答:
在完全启动了ucore后,虚拟地址和线性地址相等,都等于物理地址加上0xc0000000,如果需要虚拟地址和物理地址相等,可以考虑更新gdt,更新段映射,使得“虚拟地址=线性地址-0xc0000000”,这样就可以实现虚拟地址和物理地址相等。

四、实验结果

在lab2目录下执行make grade指令,得到输出结果如图:

五、实验心得

本次实验主要是关于物理内存管理,虽然这部分课还没上,但因为我组负责的小班讲述的内容就是物理内存管理,故本次实验理解和实现的难度得到了一定的下降。
本次实验巩固了我对物理内存管理的理解,更重要的是提高了动手操作的能力,加深了对物理内存、虚拟地址以及两者之间协作工作的理解。

ucore Lab2 物理内存管理相关推荐

  1. lab2物理内存管理实现

    0.虚拟内存的分配(malloc,free) 从操作系统角度来看,进程分配内存有2种方式,分别由2个系统调用完成:brk和mmap(不考虑共享内存). brk是将数据段(.data)的最高地址指针_e ...

  2. ucore物理内存管理

    物理内存管理 (1)编译运行 uCore Lab2的工程代码 (2)完成uCore Lab2 练习 1-3的编程作业 思考如何实现uCore Lab2扩展练习1-2 提交uCore Lab2实验报告的 ...

  3. ucore lab2

    UCORE实验2 实验目的 理解基于段页式内存地址的转换机制 理解页表的建立和使用方法 理解物理内存的管理方法 实验内容 本次实验包含三个部分.首先了解如何发现系统中的物理内存:然后了解如何建立对物理 ...

  4. ucore lab2学习笔记整理

    本次实验主要完成ucore内核对物理内存的管理. ucore被启动后,需要探测系统的物理内存布局来了解哪些物理内存空间是可用的.ucore是使用e820h中断来获取内存信息,而这个中断必须在实模式下使 ...

  5. ucore lab2 操作系统实验

    LAB2: 知识准备 (通过操作系统原理教材.gitbook实验指导书.清华大学教学视频以及其他相关的资料进行学习) 1.特权级以及特权级的转换 (在清华大学教学视频中格外详细讲述了此内容,故结合视频 ...

  6. 解析Winndows 2000/XP物理内存管理

    解析Winndows 2000/XP物理内存管理    物理内存是相对比较紧张的资源,合理利用将是一个操作系统的性能的关键.Windows 2000/XP内部使用一个称为页框数据库(Page Fram ...

  7. OS学习笔记-7(清华大学慕课)实验二物理内存管理

    实验二物理内存管理 X86特权级 分成4个特权级 内核在level0,应用程序在level3 一开始想用4个特权级,但现在一般2个就够了 cpu完成特权级检查 段选择子 DPL描述了段的优先级

  8. 内存管理两部曲之物理内存管理

    内存管理总览 返利网站 m.cpa5.cn 先笼统地总结下内存管理到底是干啥的,下面这段话摘自<现代操作系统 - 第 3 版>: 内存管理的任务就是有效地管理内存,即记录哪些内存是正确使用 ...

  9. 【清华大学】操作系统 陈渝 Part3 ——物理内存管理 之 连续内存分配

    [清华大学]操作系统 陈渝 Part3 --物理内存管理 之 连续内存分配 3.1计算机体系结构及内存分层 计算机体系机构 内存体系层次 管理内存方法 3.2地址空间 & 地址生成 地址空间定 ...

  10. Linux 物理内存管理涉及的三大结构体之struct zone

    从Linux 物理内存管理涉及的三大结构体之struct page 中,大概知道了UMA和NUMA概念,同时也知道在每个node对应的内存范围内,都会将其分成不同的内存管理区域zone.之所以分成几类 ...

最新文章

  1. 用g++编译C++ 的流程示例如下
  2. 原创 | 常见损失函数和评价指标总结(附代码)
  3. pxe+kickstart无人值守安装
  4. 262K Color
  5. base64加密原理及python、C语言代码实现
  6. Qt学习(十):QT连接mysql(增加、删除、遍历)
  7. Seeed Raspberry Pi广角摄像/相机模块 支持Pi所有版本 OV5647
  8. Android Studio 之下载安装
  9. php自动安装myqsl,php – 在自制的小牛上安装MySQL麻烦
  10. python中如何计算集合的长度_Python如何计算序列长度 python dataframe中元素如何统计?...
  11. 无法在此计算机上安装vmware,电脑中虚拟机无法安装VMware Tools提示D盘找不到setup.exe如何解决...
  12. LeetCode 718最长重复子数组
  13. 智能优化算法应用:基于麻雀搜索算法无线传感器网络(WSN)覆盖优化 - 附代码
  14. AI Challenger 2018:细粒度用户评论情感分类冠军思路总结
  15. linux中的jiffies变量
  16. vue学习笔记-接口调用-axios
  17. abd串口工具使用教程_一体机电脑维修工具下载及使用教程
  18. 基础篇:6)形位公差标注(GDT标准)-总章
  19. 00007__js自执行函数(function(){})()前加个分号是什么意思
  20. SQL优化(三) 查询条件优化

热门文章

  1. 三大抽样分布:卡方分布,t分布和F分布的简单理解
  2. POS机全国产化电子元件推荐方案
  3. 【人月神话】01 人月神话
  4. 自从硬派网倒闭后,就没有什么好看的IT硬件网站了
  5. dB,dBm W之换算关系
  6. 行为树(Behavior Tree)
  7. 网上下载或自己编程实现任意一种多变量决策树算法,并观察其在西瓜数据集3.0上产生的结果。
  8. pythonqq机器人酷q_基于python和酷Q的QQ机器人开发实践(1)
  9. linux硬盘序列号在哪看,linux下怎样查看硬盘型号和硬盘序列号
  10. 适合APP的开发模式——敏捷开发