实验二:物理内存管理


练习0:填写已有实验

将lab1中已完成的代码更新到lab2中,在这里分别尝试了diff+patch和meld两种方法
在lab2目录下,trap.c的更新如下(注意可能需要手动在.patch文件中处理合并部分)

diff -c ./kern/trap/trap.c ../lab1/kern/trap/trap.c > ./kern/trap/trap.patch
patch -p2 -i ./kern/trap/trap.patch

对kdebug.c的更新使用meld,命令行输入meld后直接拖入要合并的文件并选择合并方式即可


练习1:实现first-fit连续物理内存分配算法

1.1 理解ucore的机制

首先来看页的结构定义在kern/mm/memlayout.h

/* ** struct Page - Page descriptor structures. Each Page describes one* physical page. In kern/mm/pmm.h, you can find lots of useful functions* that convert Page to other data types, such as phyical address.* */
struct Page {int ref;                        // page frame's reference counteruint32_t flags;                 // array of flags that describe the status of the page frameunsigned int property;          // the num of free block, used in first fit pm managerlist_entry_t page_link;         // free list link
};/* Flags describing the status of a page frame */
#define PG_reserved                 0
#define PG_property                 1      
  • ref表示页被引用的计数器,当有一个虚拟页映射到了这个结构描述的物理页,计数器加1,反之减1,当变为0的时候要设置其标记位表示页是未分配的
  • flags表示页的状态标记,有2个标记,bit0表示此页是否被保留,若被保留则设置为1,bit1表示此页是否是空闲的,若是空闲则设置为1,可以通过SetPageReserved等宏进行标记的设置
  • property表示某连续内存空闲块的大小,即地址连续空闲页的个数,需要设置此变量的页是头页,连续内存空闲块地址最小的一页
  • page_link表示把多个连续内存空闲块链接在一起的双向链表指针,具体定义及操作参考libs/list.h

为了有效管理一系列地址不连续的多个小连续内存空闲块(块内的物理页是连续的),定义了free_area_t数据结构,包含有list_entry_t双向链表指针和nr_free记录当前空闲页个数的变量

/* free_area_t - maintains a doubly linked list to record free (unused) pages */
typedef struct {list_entry_t free_list;         // the list headerunsigned int nr_free;           // # of free pages in this free list
} free_area_t;

ucore为了管理内存分配和释放,建立了一个物理内存页管理框架包含一系列操作,定义在kern/mm/pmm.h

// pmm_manager is a physical memory management class. A special pmm manager - XXX_pmm_manager
// only needs to implement the methods in pmm_manager class, then XXX_pmm_manager can be used
// by ucore to manage the total physical memory space.
struct pmm_manager {const char *name;                                 // XXX_pmm_manager's namevoid (*init)(void);                               // initialize internal description&management data structure// (free block list, number of free block) of XXX_pmm_manager void (*init_memmap)(struct Page *base, size_t n); // setup description&management data structcure according to// the initial free physical memory space struct Page *(*alloc_pages)(size_t n);            // allocate >=n pages, depend on the allocation algorithm void (*free_pages)(struct Page *base, size_t n);  // free >=n pages with "base" addr of Page descriptor structures(memlayout.h)size_t (*nr_free_pages)(void);                    // return the number of free pages void (*check)(void);                              // check the correctness of XXX_pmm_manager
};

1.2 first-fit方法的实现

first-fit是通过遍历空闲块链表,将第一个符合要求的块分配出去的算法,包含改变标记位、从链表中删除、处理多余的页(符合要求的块大于所需的大小)
实验1中重点实现init_memmapalloc_pagesfree_pages这三个函数,基于实验代码中部分完成的部分进一步修改如下

/*reuse the demo default_init fun*/
static void
default_init(void) {list_init(&free_list);nr_free = 0;
}static void
default_init_memmap(struct Page *base, size_t n) {assert(n > 0);struct Page *p = base;for (; p != base + n; p ++) {assert(PageReserved(p));                       p->flags = 0;                                  SetPageProperty(p);p->property = 0;set_page_ref(p, 0);list_add_before(&free_list, &(p->page_link)); //'add before' -> low to high addr}base->property = n;                               //head page need to set propertynr_free += n;
}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, *len;while ((le = list_next(le)) != &free_list) {struct Page *p = le2page(le, page_link);if (p->property >= n) {                       //first-fit then breakpage = p;break;}}if (page != NULL) {if (page->property > n) {                     struct Page *p = page + n;p->property = page->property - n;         //update the spare pages' head page}nr_free -= n;for(int i=0; i<n; i++){                       //initialize the allocated pageslen = list_next(le);struct Page *pp = le2page(le, page_link);SetPageReserved(pp);ClearPageProperty(pp);list_del(le);le = len;}}return page;
}static void
default_free_pages(struct Page *base, size_t n) {assert(n > 0);assert(PageReserved(base));nr_free += n;struct Page *p;list_entry_t *le = &free_list;while((le = list_next(le)) != &free_list){p = le2page(le, page_link);if(p > base){                                 //to find the correct position to insert(from low to high addr)break;}}for(p = base; p < base + n; p++){                 //reset the freed pages and insert them into page_linklist_add_before(le, &(p->page_link));p->flags = 0;p->property = 0;set_page_ref(p, 0);ClearPageReserved(p);SetPageProperty(p);}base->property = n;                               //assume base is a head pageif(base + n == le2page(le, page_link)){           //merge with high addrbase->property += p->property;p->property = 0;}le = list_prev(&(base->page_link));p = le2page(le, page_link);if(le != &free_list && p == base - 1){            //merge with low addrwhile(le != &free_list){if(p->property > 0){                      //find the previous free block's head page and mergep->property += base->property;base->property = 0;                   //base is not a head page, reset its propertybreak;}le = list_prev(le);p = le2page(le, page_link);}}
}

练习2:实现寻找虚拟地址对应的页表项

2.1 理解ucore段/页表寻址机制

ucore下的段机制使得虚拟地址到线性地址存在对等映射的关系,而二级页表使得线性地址到物理地址存在映射关系,基本模式如下图(没有体现TLB等因素),地址映射的四个阶段可以参考实验指导手册

https://chyyuu.gitbooks.io/ucore_os_docs/content/lab2/lab2_3_3_5_4_maping_relations.html

具体到分页机制,ucore在kern/mm/mmu.h中定义了线性地址的组成及一些宏操作,线性地址由10位页目录表索引、10位页表项索引和12位页内偏移构成

// A linear address 'la' has a three-part structure as follows:
//
// +--------10------+-------10-------+---------12----------+
// | Page Directory |   Page Table   | Offset within Page  |
// |      Index     |     Index      |                     |
// +----------------+----------------+---------------------+
//  \--- PDX(la) --/ \--- PTX(la) --/ \---- PGOFF(la) ----/
//  \----------- PPN(la) -----------/
//
// The PDX, PTX, PGOFF, and PPN macros decompose linear addresses as shown.
// To construct a linear address la from PDX(la), PTX(la), and PGOFF(la),
// use PGADDR(PDX(la), PTX(la), PGOFF(la)).// page directory index
#define PDX(la) ((((uintptr_t)(la)) >> PDXSHIFT) & 0x3FF)// page table index
#define PTX(la) ((((uintptr_t)(la)) >> PTXSHIFT) & 0x3FF)// page number field of address
#define PPN(la) (((uintptr_t)(la)) >> PTXSHIFT)// offset in page
#define PGOFF(la) (((uintptr_t)(la)) & 0xFFF)// construct linear address from indexes and offset
#define PGADDR(d, t, o) ((uintptr_t)((d) << PDXSHIFT | (t) << PTXSHIFT | (o)))// address in page table or page directory entry
#define PTE_ADDR(pte)   ((uintptr_t)(pte) & ~0xFFF)
#define PDE_ADDR(pde)   PTE_ADDR(pde)

2.2 get_pte函数实现

需要完成的get_pte实际上就是获得Page Table中Entry的地址,其函数说明如下

//get_pte - get pte and return the kernel virtual address of this pte for la
//        - if the PT contians this pte didn't exist, alloc a page for PT
// parameter:
//  pgdir:  the kernel virtual base address of PDT
//  la:     the linear address need to map
//  create: a logical value to decide if alloc a page for PT
// return vaule: the kernel virtual address of this pte

则本函数的基本流程为

Created with Raphaël 2.1.0获取页目录表基地址、线性地址、标记获得页目录表项内容是否存在?返回页表项的虚拟地址是否创建?创建页表并初始化返回NULLyesnoyesno

实现如下,与lab2_result中的实现略有不同,这里不对比分析

pde_t *pdep = &pgdir[PDX(la)];                        //get page directory entry(physical addr)
if(!(*pdep & PTE_P)){struct Page *page;if(!create || (page = alloc_page()) == NULL){return NULL;}set_page_ref(page,1);uintptr_t pa = page2pa(page);                     //get the new page's physical addrmemset(KADDR(pa), 0, PGSIZE);                     //initialize the memory(need KADDR() to get the virtual addr as OS process virual addr)*pdep = pa | PTE_P | PTE_W | PTE_U;               //set flags
}
return &((pte_t *)KADDR(PDE_ADDR(*pdep)))[PTX(la)];   //PDE_ADDR(): align to 4k, KADDR(): convert pa to va, PTX(): get page table index

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

在练习2的基础上,练习3提供了一些函数更为方便的释放页并更新页表映射,直接给出代码如下

if (*ptep & PTE_P) {                                  //check if this page table entry is presentstruct Page *page = pte2page(*ptep);              //find corrsponding page to pteif (page_ref_dec(page) == 0) {                    //decrease page reffree_page(page);                              //if page ref == 0 then free it}*ptep = 0;                                        //clear second page table entrytlb_invalidate(pgdir, la);                        //update TLB
}

总结

在完成所有内容后,调用make debug并在GDB中输入continue后运行结果如下,函数功能实现成功

lab2$ (THU.CST) os is loading ...Special kernel symbols:entry  0xc010002a (phys)etext  0xc0105a3e (phys)edata  0xc0117a36 (phys)end    0xc0118968 (phys)
Kernel executable memory footprint: 99KB
ebp:0xc0116f48 eip:0xc0100a52 args:0x00010094 0x00010094 0xc0116f78 0xc01000a9kern/debug/kdebug.c:309: print_stackframe+22
ebp:0xc0116f58 eip:0xc0100d3e args:0x00000000 0x00000000 0x00000000 0xc0116fc8kern/debug/kmonitor.c:129: mon_backtrace+10
ebp:0xc0116f78 eip:0xc01000a9 args:0x00000000 0xc0116fa0 0xffff0000 0xc0116fa4kern/init/init.c:49: grade_backtrace2+19
ebp:0xc0116f98 eip:0xc01000cb args:0x00000000 0xffff0000 0xc0116fc4 0x00000029kern/init/init.c:54: grade_backtrace1+27
ebp:0xc0116fb8 eip:0xc01000e8 args:0x00000000 0xc010002a 0xffff0000 0xc010006dkern/init/init.c:59: grade_backtrace0+19
ebp:0xc0116fd8 eip:0xc0100109 args:0x00000000 0x00000000 0x00000000 0xc0105a40kern/init/init.c:64: grade_backtrace+26
ebp:0xc0116ff8 eip:0xc010007a args:0x00000000 0x00000000 0x0000ffff 0x40cf9a00kern/init/init.c:29: kern_init+79
memory management: default_pmm_manager
e820map:memory: 0009fc00, [00000000, 0009fbff], type = 1.memory: 00000400, [0009fc00, 0009ffff], type = 2.memory: 00010000, [000f0000, 000fffff], type = 2.memory: 07ee0000, [00100000, 07fdffff], type = 1.memory: 00020000, [07fe0000, 07ffffff], type = 2.memory: 00040000, [fffc0000, ffffffff], type = 2.
check_alloc_page() succeeded!
check_pgdir() succeeded!
check_boot_pgdir() succeeded!
-------------------- BEGIN --------------------
PDE(0e0) c0000000-f8000000 38000000 urw|-- PTE(38000) c0000000-f8000000 38000000 -rw
PDE(001) fac00000-fb000000 00400000 -rw|-- PTE(000e0) faf00000-fafe0000 000e0000 urw|-- PTE(00001) fafeb000-fafec000 00001000 -rw
--------------------- END ---------------------
++ setup timer interrupts
100 ticks
100 ticks

lab2需要对内存管理机制有深入的了解,博主还没有很好的掌握,先写这么多

操作系统实验二实验报告相关推荐

  1. 大学计算机实验二报告表答案,北理大学计算机实验基础实验二实验报告表答案...

    <北理大学计算机实验基础实验二实验报告表答案>由会员分享,可在线阅读,更多相关<北理大学计算机实验基础实验二实验报告表答案(4页珍藏版)>请在人人文库网上搜索. 1.实验二实验 ...

  2. python编程图书批发商店的某本书的零售价是26.5_根据实验指导书,完成实验2的任务一与任务三,使用 实验二(实验报告).docx 完成报告并提交。_学小易找答案...

    [简答题]从键盘输入 n(0 [简答题]完成课本P89,查询学生成绩,提交源代码 [单选题]企业本期生产产品直接耗用原材料 3000 元,生产车间管理方面耗用原材料 2000 元,正确的会计分录是( ...

  3. java上机实验实验报告_Java实验二实验报告.doc

    Java实验二实验报告 本科学生实验报告 ( 二 ) 姓名 学院 计算机科学学院 专业 计算机科学与技术 班级 实验课程名称 Java面向对象设计 试验时间 2012 年 10 月 14 日 指导教师 ...

  4. 20135333苏正生实验二实验报告

    实验报告 课程: Java程序设计 班级: 1353 姓名: 苏正生 学号: 2015333 成绩: 指导教师: 娄家鹏 实验日期: 2015.5.6 实验密级: 预习程度: 实验时间: 3:20~5 ...

  5. 大学计算机实验二报告表答案,北理大学计算机实验基础实验二实验报告表答案(1页)-原创力文档...

    实验二实验报告表 实验名称: 学号姓名:班级:实验时间: 实验报告表 2-1 数值型数据在计算机中的二进制实验记录表 十进制整数分 输入十进制整数 内存整型数据 内存地址号 类 任意正整数 7 000 ...

  6. 20202413 2021-2022-2 《网络与系统攻防技术》实验二实验报告

    20202413 2021-2022-2 <网络与系统攻防技术>实验二实验报告 文章目录 20202413 2021-2022-2 <网络与系统攻防技术>实验二实验报告 1.实 ...

  7. ORACLE与数据库原理实验 实验二 实验数据库的建立(答案全)

    实验二 实验数据库的建立 [实验目的] [预备知识] [实验内容] [实验目的] 1. 熟悉和掌握 SQL的 Create Table, Drop Table, Alter Table语句语法: 2. ...

  8. 周信东c语言实验二实验报告,周信东主编最新版C语言程序设计基础实验一实验报告.doc...

    周信东主编最新版C语言程序设计基础实验一实验报告.doc 下载提示(请认真阅读)1.请仔细阅读文档,确保文档完整性,对于不预览.不比对内容而直接下载带来的问题本站不予受理. 2.下载的文档,不会出现我 ...

  9. 《Java程序设计》实验二 实验报告

    实验二 Java面向对象程序设计 实验内容 初步掌握单元测试和TDD 理解并掌握面向对象三要素:封装.继承.多态 初步掌握UML建模 熟悉S.O.L.I.D原则 了解设计模式 实验要求 1.没有Lin ...

最新文章

  1. 攻读计算机视觉和机器学习硕士给我带来了什么?
  2. Unity Shader基本例子
  3. Mycat源码中的单例模式
  4. ASP.NET MVC 学习之路-4
  5. Java 文件操作 File 及 RandomAccessFile
  6. php 整数 比较,php中字符串和整数比较
  7. 开发短信发送程序的几则技巧
  8. 二阶偏微分方程组 龙格库塔法_数值方法(MATLAB版)(原书第3版)[Numerical Methods Using MATLAB,Third Edition]pdf...
  9. Tomcat相关总结
  10. python的浮点数_Python的浮点数损失精度问题
  11. zabbix创建自定义监控项
  12. CodeCombat 落地马来西亚巴生中华小学,支持人工智能远程教学
  13. win10 64位 JavaJDK的下载、安装与配置。
  14. jQuery,JS实现自定义鼠标右键菜单
  15. 机器学习可解释性之shap模块的使用——基础用法(一)
  16. 尚德机构第四季度营收5.688亿元 亏损大幅缩小
  17. .frm mysql_mysqlfrm使用
  18. 【SPRD CAMERA】1 HAL层初始化流程
  19. Cocos Creator 开发入门
  20. Unity 代码修改宏名并一键打包

热门文章

  1. 数据库课程总结(ORACLE)
  2. Web大学生网页作业成品 bootstrap响应式网站开发 基于HTML+CSS+JS+Bootstrap制作火锅美食网站(4页)
  3. Angular $q 完全指南
  4. ubuntu安装sougoupinyin[sogoupinyin_2.2.0.0108_amd64.deb]出坑(内附各种失败解决办法)
  5. VirtualBox 虚拟机安装Windows10,珍藏版!!!
  6. 科达实战应用平台服务器ip,H3C ME5000与科达MCU KDV8000A级联的互通案例配置
  7. A Transformer-based Approach for Source code Summarization 翻译
  8. 美式看跌期权的二叉树定价
  9. 国家提的内循环到底是个啥?
  10. android调用在线天气服务,android通过google api获取天气信息示例