lab1的实验完成后开始lab2,lab2主要是实现内存分配

实验目的:

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

在lab1的时候我们用的是段式管理,涉及到的地址都是物理地址。而lab2需要建立段页式内管管理机制。从应用程序的使用角度看是不关心具体对应的物理内存的,操作系统提供一个可用的连续内存空间(虚拟的)给应用程序使用,这样会更方便应用程序编写。

lab2主要分三部分:

  • 首先要了解的是如何发现系统(硬件)的物理内存

  • 建立对物理内存的初步管理

  • 页表相关的操作(虚拟地址和物理地址的映射等处理)

lab2主要包括了5个实验,3个一般的和2个challenge

前置条件

  1. 做完lab1的实验

  2. 阅读lab2课件

  3. 了解探测物理内存布局的方法(实现物理内存探测)

  4. 需要了解理论课讲的几种内存分配算法

页表的虚拟地址是连续的,而且所有进程的页表起始虚拟地址都是一样的(就是VPT);而物理地址可以是不连续的。

练习0:填写已有实验

把lab1的内容合并到lab1,用diff和patch等工具即可。再不济,lab1的练习涉及的代码也不多,可以直接copy(不推荐)。

练习1:实现 first-fit 连续物理内存分配算法(需要编程)

需要实现的方法

  1. default_init(initialize internal description&management data structure free block list, number of free block)

  2. default_init_memmap(setup description&management data structcure according to the initial free physical memory space)

  3. default_alloc_pages(allocate >=n pages, depend on the allocation algorithm)

  4. default_free_pages(free >=n pages with “base” addr of Page descriptor structures(memlayout.h))

工程里面代码的注释介绍的很详细,且有一些提示类的代码,我们需要完善。

default_init

static void
default_init(void) {list_init(&free_list);nr_free = 0;
}

default_init_memmap

static void
default_init_memmap(struct Page *base, size_t n) {// 需要循环设置每一页的flags, property, ref, 且要在链表中连接起来(1->2->3)// 然后把这一段内存区域加入到free_list中,设置nr_freeassert(n > 0);struct Page *p = base;for (; p != base + n; p++) {assert(PageReserved(p));p->flags = p->property = 0;set_page_ref(p, 0);}// 设置这段内存区域第一页的属性SetPageProperty(base);base->property = n;nr_free += n;// 加入到free_list中// 双向循环链表// free_list<->add1_pages<->add2_pages<->add3_pages<->free_listlist_add(&free_list, &base->page_link);
}

default_alloc_pages

static struct Page *
default_alloc_pages(size_t n) {assert(n > 0);if (n > nr_free) {return NULL;}struct Page *page = NULL;list_entry_t *le = &free_list;while ((le = list_next(le)) != &free_list) {struct Page *p = le2page(le, page_link);// 找到符合条件的if (p->property >= n) {page = p;break;}}if (page != NULL) {// 如果分配n个后还有page页,则后面的补上if (page->property > n) {struct Page *pn = page + n;pn->property = page->property - n;SetPageProperty(pn);list_add_after(&page->page_link, &pn->page_link);}ClearPageProperty(page);nr_free -= n;list_del(&page->page_link);}return page;
}

default_free_pages

static void
default_free_pages(struct Page *base, size_t n) {// 逻辑如下:// 1 先把base的属性更新// 2 循环在free_list中查找// 2.1 *base可能刚好在某个空闲块的后面// 2.2 *base可能刚好在某个空闲块的前面// 2.3 可能在尾部或者某两个之间// 2.4 对应的物理页地址没有问题的情况下插入到空闲链表中// 3、可能刚好应该插入的头的情况// 先做一些处理(设置flags, ref, 页链表头的property等)assert(n > 0);struct Page *p = base;for (; p != base + n; p++) {assert(!PageReserved(p) && !PageProperty(p));p->flags = 0;set_page_ref(p, 0);}base->property = n;SetPageProperty(base);struct Page *t = base + base->property;// 再往合适的位置(free_list)插int i = 0;list_entry_t *le = &free_list;while ((le = list_next(le)) != &free_list) {p = le2page(le, page_link);i++;// 刚好在前面// 两个if不能直接break,因为可能存在 // p + p->property = base, 下一个链表// base + base->property = p(next le)if (base + base->property == p) {base->property += p->property;// tempP不是头ClearPageProperty(p);list_del(&(p->page_link));}// 刚好在后面if (p + p->property == base) {p->property += base->property;ClearPageProperty(base);base = p;list_del(&(p->page_link));}}le = &free_list;while ((le = list_next(le)) != &free_list) {// 在中间(前插,即找到比base地址大的,插入前面)p = le2page(le, page_link);if (base + base->property <= p) {assert(base + base->property != p);break;}}list_add_before(le, &(base->page_link));nr_free += n;
}

请在实验报告中简要说明你的设计实现过程。请回答如下问题:

  • 你的first fit算法是否有进一步的改进空间

    暂时没想到,可能要用线段树来实现

练习2:实现寻找虚拟地址对应的页表项(需要编程)

get_pte也就是给定线性地址,得到线性地址对应的二级页表项(page table entry)对应的内核虚地址(kernel virtual address),二级页表项不存在,分配一个包含此项的二级页表。

根据理论课,及Intel的参考手册大概可以知道地址的映射关系。

此函数入参为pgdir指针,线性地址,及是否给PT分配一个页,出参为pte的虚地址。从线性地址的转换可以想到大概步骤如下:

  • 线性地址(la)前10位,在pgdir(页目录表中查找)对应的页表项,得到指向页表项的指针pdep。
  • 检查pdep指向的页表向是否有效(即指向的二级页表向是否存在)。
  • 如果无效(不存在),分配一个新的页(Page)为一个新的二级页表(一页为4KB,即分配的一个page,刚好可以存1024个page table entry)。把这个页的物理转换为内核虚拟地址,用memset方法,将内容清零。
  • 将上面得到的地址填入到PDE中,设置为可读可写。
  • 获取PDE中的物理地址,转换为内核虚拟地址,即得到二级页表的起始地址。再加上PTE对应的偏移量,就得到真正PTE的地址。

代码如下:

pte_t *
get_pte(pde_t *pgdir, uintptr_t la, bool create) {// typedef uintptr_t pde_t// PDX 左边10位(PDE)// PTX 中间10位(PTE)// KADDR - takes a physical address and returns the corresponding kernel virtual address// #define PTE_ADDR(pte)   ((uintptr_t)(pte) & ~0xFFF) address in page table or page directory entry// #define PDE_ADDR(pde)   PTE_ADDR(pde) address in page table or page directory entry// pdep: page dirtory pde_t *pdep = NULL;uintptr_t pde = PDX(la);pdep = &pgdir[pde];// 非present也就是不存在这样的page(缺页),需要分配页if (!(*pdep & PTE_P)) {struct Page *p;// 如果不需要分配或者分配的页为NULLif (!create || (p = alloc_page()) == NULL) {return NULL;}set_page_ref(p, 1);// page table的索引值(PTE)uintptr_t pti = page2pa(p);// KADDR: takes a physical address and returns the corresponding kernel virtual address.memset(KADDR(pti), 0, sizeof(struct Page));// 相当于把物理地址给了pdep// pdep: page directory entry point*pdep = pti | PTE_P | PTE_W | PTE_U;}// 先找到pde address// address in page table or page directory entry// 0xFFF = 111111111111// ~0xFFF = 1111111111 1111111111 000000000000// #define PTE_ADDR(pte)   ((uintptr_t)(pte) & ~0xFFF)// #define PDE_ADDR(pde)   PTE_ADDR(pde)uintptr_t pa = PDE_ADDR(*pdep);// 再转换为虚拟地址(线性地址)// KADDR = pa >> 12 + 0xC0000000// 0xC0000000 = 11000000 00000000 00000000 00000000pte_t *pde_kva = KADDR(pa);// 需要映射的线性地址// 中间10位(PTE)uintptr_t need_to_map_ptx = PTX(la);return &pde_kva[need_to_map_ptx];
}

请在实验报告中简要说明你的设计实现过程。请回答如下问题:

  • 请描述页目录项(Page Directory Entry)和页表项(Page Table Entry)中每个组成部分的含义以及对ucore而言的潜在用处。

    参考Intel手册:

    从结构上可以看出来,页目录项(Page Directory Entry)和页表项(Page Table Entry)差不多,只是12-31位代表的含义不相同。

    • P 存在位(present)

    • R/W 读/写位(Read/Write)

    • U/S 访问该页需要的特权级

    • PWT write through(为1表示此项采用通写方式,表示该页不仅是普通内存,还是高速缓存)

    • PCD 若为1表示该页启用高速缓存,为0表示禁止将该页缓存

    • A 访问位,若为1表示该页被 CPU 访问过啦,所以该位是由 CPU 设置的。

    • D 脏页位,当 CPU 个页面执行写操作时,就会设置对应页表项的D位为 1,此项仅针对页表项有效,并不会修改页目录项中的位。

    • PAT 页属性位,在页一级的粒度上设置内存属性。

    • G 全局位,与TLB有关,为1表示该页是全局页,该页在高速缓存TLB中一直保存。

    • Avail 可用位,为1表示用户进程可用该页,为0则不可用。对操作系统无效。

  • 如果ucore执行过程中访问内存,出现了页访问异常,请问硬件要做哪些事情?

    出现页访问异常

练习3:释放某虚地址所在的页并取消对应二级页表项的映射(需要编程)

这个比较简单,大概步骤如下:

  • 检查是否ptep是否存在
  • 如果存在,则根据ptep得到对应的page,pqge的ref减一,如果减一后为0,则释放page(free_page)
  • 清除ptep,刷新tlb

代码如下:

static inline void
page_remove_pte(pde_t *pgdir, uintptr_t la, pte_t *ptep) {if ((*ptep & PTE_P)) {struct Page *page = pte2page(*ptep);if (page_ref_dec(page) == 0) {free_page(page);}// clear second page table entry*ptep = 0;// flush tlbtlb_invalidate(pgdir, la);}}

请在实验报告中简要说明你的设计实现过程。请回答如下问题:

  • 数据结构Page的全局变量(其实是一个数组)的每一项与页表中的页目录项和页表项有无对应关系?如果有,其对应关系是啥?

    pages的每一项与页表中的页目录项和页表项有对应,pages每一项对应一个物理页的信息。一个页目录项对应一个页表,一个页表项对应一个物理页。假设有N个物理页,pages的长度为N,而页目录项、页表项的前20位对应物理页编号。

    如下图所示:

    一个PDE对应1024个PTE,一个PTE对应1024个page。

  • 如果希望虚拟地址与物理地址相等,则需要如何修改lab2,完成此事? 鼓励通过编程来具体完成这个问题

    只需要把KERNBASE从0xC0000000改成0x00000000,且把kernel.ld里面的0xC0100000改为0xC0000000

扩展练习Challenge:buddy system(伙伴系统)分配算法(需要编程)

请在实验报告中简要说明你的设计实现过程。请回答如下问题:

  • 数据结构Page的全局变量(其实是一个数组)的每一项与页表中的页目录项和页表项有无对应关系?如果有,其对应关系是啥?
  • 如果希望虚拟地址与物理地址相等,则需要如何修改lab2,完成此事? 鼓励通过编程来具体完成这个问题

有点难度,暂未实现,后续实现后补充上去

扩展练习Challenge:任意大小的内存单元slub分配算法(需要编程)

slub算法,实现两层架构的高效内存单元分配,第一层是基于页大小的内存分配,第二层是在第一层基础上实现基于任意大小的内存分配。可简化实现,能够体现其主体思想即可。

  • 参考linux的slub分配算法/,在ucore中实现slub分配算法。要求有比较充分的测试用例说明实现的正确性,需要有设计文档。

有点难度,暂未实现,后续实现后补充上去

参考:

《ucore lab2》实验报告

操作系统真相还原 第五章 保护模式进阶,向内核迈进

TR 寄存器和 Task State 段

ucoreOS_lab2 实验报告

Address translation and sharing using page tables

ucore_lab2实验报告相关推荐

  1. 2019春第二次课程设计实验报告

    2019春第二次课程设计实验报告 一.实验项目名称: 贪吃蛇游戏编写: 二.实验项目功能描述: 这个实验主要是实现游戏的正常运行,实现的目标是对小蛇移动的控制, 同时对小蛇数据的保存,如何实现转弯的效 ...

  2. JAVA第二次验证设计性实验报告

    [实验任务一]:素数输出 (3)实验报告中要求包括程序设计思想.程序流程图.源代码.运行结果截图.编译错误分析等内容. 1.   实验内容 (1)计算并输出3~100之间的素数. (2)编程满足下列要 ...

  3. 计算机网络实验报告建立校园网,计算机网络实验报告

    设计性实验报告 一.实验目的 通过对网络设备的连通和对拓扑的分析,加深对常见典型局域网拓扑的理解:通过路由建立起网络之间的连接,熟悉交换机.路由器的基本操作命令,了解网络路由的设计与配置. 二.背景描 ...

  4. c语言链表最高响应比优先,操作系统--最高响应比优先调度算法实验报告..doc

    操作系统--最高响应比优先调度算法实验报告. 进程调度一.实验题目与要求 编写程序完成批处理系统中的作业调度,要求采用响应比高者优先的作业调度算法.实现具体包括:首先确定作业控制块的内容和组成方式:然 ...

  5. 计算机网络实验可变长子网掩码,计算机网络实验3-子网掩码与划分子网实验报告.docx...

    PAGE PAGE # / 5 上机实验报告三 -.实验目的 (1 )掌握子网掩码的算法. 了解网关的作用. 熟悉模拟软件 packet tracer5.3的使用. 二.实验内容 1.( 1) 172 ...

  6. 实验报告Linux操作系统基本命令,linux操作系统实验报告全部.doc

    linux操作系统实验报告全部 计算机操作系统 实验报告 学 号:姓 名:提交日期:2014.12.15成 绩: 东北大学秦皇岛分校 [实验题目]熟悉Linux/UNIX操作系统[实验目的]1.熟悉L ...

  7. 递归下降文法C语言实验报告,递归下降语法分析器实验报告.doc

    递归下降语法分析器实验报告 编译原理实验报告 题目: 递归下降语法分析器 学 院 计算机科学与技术 专 业 xxxxxxxxxxxxxxxx 学 号 xxxxxxxxxxxx 姓 名 宁剑 指导教师 ...

  8. labview简易计算机实验报告,labview实验报告..doc

    学院:电气工程学院 班级:自112班 姓名:何富裕 学号:1112011060 实验一 一.实验目的 熟悉LabVIEW软件的基本编程环境. 二.实验内容 创建并保存一个VI程序.此VI要实现的功能是 ...

  9. c语言实验报告管理系统,C语言实验报告-学生信息资管理系统.doc

    C语言实验报告-学生信息资管理系统 C语言实验报告 院系: 数学与计算科学学院 班级: 信息与计算科学2班 姓名: 学号: 2011年12月21日 一.问题描述 编写一个信息管理系统,包括姓名.性别. ...

最新文章

  1. 盘点丨那些顶级的AI机器人“大脑”
  2. C++中四种类型转换符:static_cast、dynamic_cast、reinterpret_cast和const_cast要点解析
  3. k8s的pod资源管理与配置使用凭证的harbor仓库
  4. Codevs2157 配对
  5. JavaFX 2.0和Scala,像牛奶和饼干
  6. 以我的视角看java编程世界
  7. 隐藏html文本节点,javascript-D3-仅显示/隐藏单击节点的文本
  8. js,同意后,才可已点击注册按钮
  9. Problem 69:Totient maximum
  10. 硬盘故障时如何强制关机:Input/output error
  11. .net 5和.net core_开源仿真器 EpicSim 运行 SM3_core
  12. java初级程序员成长之路
  13. android照片同步到另一部手机,换手机后怎么把照片转移到新手机上?
  14. ProcessStartInfo处理方法
  15. [ 常用工具篇 ] 还在嫌截图麻烦?快来使用 Win10 原生的截图工具 Snipping Tool 吧
  16. python支付宝自动支付_python 调用支付宝支付
  17. 会放弃的人生才会更洒脱
  18. Bitflip问题案例分析
  19. springboot--享学课堂
  20. 视频版权,JavaScript阻止360浏览器

热门文章

  1. MacOS下ohmyzsh安装
  2. 华为mate10体验华为云电脑,意外实用,以后电脑要吃灰了
  3. 已解决:EditText被底部固定栏挡住,使用AndroidBug5497Workaround出现兼容问题
  4. 文本与字体样式2.0
  5. 习题 5.17 两个乒乓球队进行比赛,各出3人。
  6. OpenNI的安装与配置
  7. 面向对象设计模式精粹——提供面向对象设计模式方面的参考资料
  8. [安装] Oracle19c rac集群安装
  9. php扩展Imagick
  10. 怎么测内阻 恒压源_测电流表内阻的几种方法