我是靠谱客的博主 腼腆万宝路,最近开发中收集的这篇文章主要介绍LAB2_Part1_Physical Page Management简介Part 1: Physical Page Management,觉得挺不错的,现在分享给大家,希望可以做个参考。

概述

简介

在本实验中,我们将编写操作系统的内存管理代码。 内存管理有两个组成部分。

第一个部分是内核的物理内存分配器,以致于内核可以分配和释放内存。 分配器将以4096字节为操作单位,称为一个页面。 我们的任务是维护一个数据结构,去记录哪些物理页面是空闲的,哪些是已分配的,以及共享每个已分配页面的进程数。 我们还要编写例程来分配和释放内存页面。

内存管理的第二个组件是虚拟内存,它将内核和用户软件使用的虚拟地址映射到物理内存中的地址。 当指令使用内存时,x86硬件的内存管理单元(MMU)执行映射,查询一组页表。 我们根据任务提供的规范修改JOS以设置MMU的页面表。

lab2包含的新源文件:

  • inc/memlayout.h
  • kern/pmap.c
  • kern/pmap.h
  • kern/kclock.h
  • kern/kclock.c

Part 1: Physical Page Management

物理内存页管理
操作系统必须跟踪物理RAM的哪些部分是空闲的以及哪些是当前正在使用的。 JOS以页为粒度管理PC的物理内存,以便它可以使用MMU映射和保护每个分配的内存。

在编写剩余的虚拟内存实现之前,您需要编写物理页分配器,因为页表管理代码为页表的存储 分配物理内存。

Exercise 1

必须实现kern/pmap.c 中的以下函数

  • boot_alloc()
  • mem_init() (only up to the call to check_page_free_list(1))
  • page_init()
  • page_alloc()
  • page_free()
    check_page_free_list() and check_page_alloc()可以测试你的物理分页器。

发现突然不像LAB1那样有详细的步骤,有点无从下手的感觉。

源码阅读

知识点:

  1. va_list va_start等等
    VA函数(variable argument function),参数可变函数。理解这个操作,头脑中需要有栈的概念,参数按序(从右到左)压栈,第一个参数在低地址位置。函数原型为
typedef char* va_list;
// 以4字节为单位对齐
#define _INTSIZEOF(n) (sizeof(n)+sizeof(int)-1)& ~(sizeof(int)-1)
// 求得参数栈的第一个参数地址
#define va_start(ap, v) (ap = (va_list)&v + _INTSIZEOF(v)) 
// 这里很巧妙,ap+SIZE指向下一个参数地址,再返回总体减去size(即又指回了当前变量) 
#define va_arg(ap, t)
(*(t *) ((ap+=_INTSIZEOF(t)) - _INTSIZEOF(t)) )
#define va_end(ap)
(ap = (va_list) 0)
步骤说明
va_list ap定义一个变差变量ap
va_start(ap, last)初始化ap,得到可变参数列表的第一个参数的确切地址。实际就是指向参数堆栈的栈顶
va_arg(ap, type)已知变量类型为type的情况下,获得下一个变参变量
va_end(ap)结束操作
  1. 感觉还是需要详细理解一下lab1中Part3的虚拟内存部分。
    在对entry_pgdir进行初始化的时候发现一个神奇的写法,暂时不明白,占个坑。
    entry_pgdir的写法也是内存映射的一个重要部分。
__attribute__((__aligned__(PGSIZE)))
pde_t entry_pgdir[NPDENTRIES] = {
// Map VA's [0, 4MB) to PA's [0, 4MB)
// 在数组定义中,这是什么写法?
[0]
= ((uintptr_t)entry_pgtable - KERNBASE) + PTE_P,
// Map VA's [KERNBASE, KERNBASE+4MB) to PA's [0, 4MB)
[KERNBASE>>PDXSHIFT]
= ((uintptr_t)entry_pgtable - KERNBASE) + PTE_P + PTE_W
};

实现

一直认为要实现虚存,感觉到无从下手,其实这个Exercise只需要将物理地址进行分页就好了。

  1. boot_alloc(), 源代码中有个骚操作,其利用链接器来得到第一个未使用的bss段的内存地址。extern char end[];不得不说 amazing !

'end’是链接器自动生成的魔术符号,它指向内核的bss段的末尾:链接器未分配给任何内核代码或全局变量的第一个虚拟地址。

// LAB 2: Your code here.
result = nextfree;
nextfree = ROUNDUP(nextfree+n, PGSIZE);
return result;
  1. page_init()其实并不复杂,但是有很多细节部分要注意好。一开始没看懂注释要表达什么意思,查看了其他大神的代码才豁然开朗。
// 1.mark page 0 as in use
// 这样我们就可以保留实模式IDT和BIOS结构,以备不时之需。
pages[0].pp_ref = 1;
// 2.
size_t i;
for (i = 1; i < npages_basemem; i++) {
pages[i].pp_ref = 0;
pages[i].pp_link = page_free_list;
page_free_list = &pages[i];
}
// 3.[IOPHYSMEM, EXTPHYSMEM)
// mark I/O hole
for (;i<EXTPHYSMEM/PGSIZE;i++) {
pages[i].pp_ref = 1;
}
// 4. Extended memory 
// 还要注意哪些内存已经被内核、页表使用了!
// first需要向上取整对齐。同时此时已经工作在虚拟地址模式(entry.S对内存进行了映射)下,
// 需要求得first的物理地址
physaddr_t first_free_addr = PADDR(boot_alloc(0));
size_t first_free_page = first_free_addr/PGSIZE;
for(;i<first_free_page;i++) {
pages[i].pp_ref = 1;
}
// mark other pages as free
for(;i<npages;i++) {
pages[i].pp_ref = 0;
pages[i].pp_link = page_free_list;
page_free_list = &pages[i];
}
  1. page_alloc(),页分配并不是我一开始理解的需要让一个虚存(填到页表项中,这样就会很复杂)指向目前的空闲物理页。所以我认为其函数的返回值struct PageInfo *很没有道理。 实际上只需要从空闲链表中取出第一个空闲页即可。如果传了标志alloc_flags则对一个PAGESIZE的内存进行清零。
// Fill this function in
struct PageInfo* pp;
if (!page_free_list) {
return NULL;
}
pp = page_free_list;
page_free_list = page_free_list->pp_link;
pp->pp_link = NULL;
//page2kva 返回值 KernelBase + 物理页号<<PGSHIFT,
虚拟地址
if (alloc_flags & ALLOC_ZERO) {
void * va = page2kva(pp);
memset(va, '', PGSIZE);
}
return pp;
  1. page_free(),这个函数编写就很简单了,注释里的hint页给得比较详细了,清楚地告诉了你需要注意的点。
if(pp->pp_link || pp->pp_ref) {
panic("pp->pp_ref is nonzero or pp->pp_link is not NULLn");
}
pp->pp_link = page_free_list;
page_free_list = pp;

结果

运行make qemu终端打印如下:

check_page_free_list() succeeded!
check_page_alloc() succeeded!
kernel panic at kern/pmap.c:745: assertion failed: page_insert(kern_pgdir, pp1, 0x0, PTE_W) < 0

check_page_free_list and check_page_alloc都已经通过了,但是在chek_page时发生了panic,因为我们的page_insert还没有是实现。之后的练习会进一步实现其功能。

最后

以上就是腼腆万宝路为你收集整理的LAB2_Part1_Physical Page Management简介Part 1: Physical Page Management的全部内容,希望文章能够帮你解决LAB2_Part1_Physical Page Management简介Part 1: Physical Page Management所遇到的程序开发问题。

如果觉得靠谱客网站的内容还不错,欢迎将靠谱客网站推荐给程序员好友。

本图文内容来源于网友提供,作为学习参考使用,或来自网络收集整理,版权属于原作者所有。
点赞(41)

评论列表共有 0 条评论

立即
投稿
返回
顶部