python编写操作系统实验_6.828 操作系统 lab2 实验报告

Introduction

该 lab 主要需要编写操作系统的内存管理部分。内存管理分为两个部分:

内核的物理内存分配器 (physical memory allocator)

使得内核可以分配、释放内存。该分配器以页为单位,JOS 中一页是 4kB。本次 lab 的任务是维护一个数据结构,该数据结构记录了物理内存分配与释放,以及多少个进程正在共享各个已分配的页。

虚拟内存 (virtual memory)

将内核和用户程序使用的虚拟地址映射到物理内存的地址中。x86 的内存管理单元 (MMU) 会在指令用到内存时完成这个映射,查询一系列页表。

在 lab2 中,新加入了几个源文件:

inc/memlayout.h // 描述虚拟地址空间的布局

kern/pmap.c // 读取物理内存大小,对虚拟地址空间进行布局

kern/pmap.h

kern/kclock.h // 操纵 PC 的时钟以及 CMOS RAM 等设备

kern/kclock.c // 这些设备中记录了物理内存大小

重点需要阅读 memlayout.h 以及 pmap.h,还需参考 inc/mmu.h。

处理冲突

在git merge lab1时,几乎必然出现冲突,以 conf/lab.mk 为例:

~/OS/lab$ more conf/lab.mk

<<<<<<< HEAD

LAB=2

PACKAGEDATE=Wed Sep 21 11:13:24 EDT 2016

=======

LAB=1

PACKAGEDATE=Wed Sep 14 12:18:32 EDT 2016

>>>>>>> lab1

其中,=======是分隔符,容易看出之上属于现在的 HEAD 即 lab2 的内容,之下属于 lab1 的内容,我们显然选择 lab2 的内容。

即手动修改 conf/lab.mk,仅保留:

LAB=2

PACKAGEDATE=Wed Sep 21 11:13:24 EDT 2016

其他冲突文件也如此处理后,直接 git add .,git commit -a提交。

Exercise 1

In the file kern/pmap.c, you must implement code for the following functions (probably in the order given).

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() test your physical page allocator. **

操作系统必需跟踪哪些物理 RAM 是空闲的,哪些正在使用。这个 exercise 主要编写物理页面分配器。它利用一个 PageInfo 结构体组成的链表记录哪些页面空闲,每个结构体对应一个物理页。因为页表的实现需要分配物理内存来存储页表,在虚拟内存的实现之前,我们需要先编写物理页面分配器。

boot_alloc 函数

static void *

boot_alloc(uint32_t n)

{

static char *nextfree; // virtual address of next byte of free memory

char *result;

// Initialize nextfree if this is the first time.

// 'end' is a magic symbol automatically generated by the linker,

// which points to the end of the kernel's bss segment:

// the first virtual address that the linker did *not* assign

// to any kernel code or global variables.

if (!nextfree) {

extern char end[];

nextfree = ROUNDUP((char *) end, PGSIZE);

}

// Allocate a chunk large enough to hold 'n' bytes, then update

// nextfree. Make sure nextfree is kept aligned

// to a multiple of PGSIZE.

//

// LAB 2: Your code here.

if (n == 0) {

return nextfree;

}

result = nextfree;

nextfree += ROUNDUP(n, PGSIZE);

return result;

}

其中,需要注意的一个是 end 到底是什么,另一个是 ROUNDUP 这个宏。其中,end 指向内核的 bss 段的末尾。利用 objdump -h kernel可以看出,bss 段已经是内核的最后一段。因此,end 指向的是第一个未使用的虚拟内存地址。而 ROUNDUP 定义在 inc/types.h 中。

~/OS/lab/obj/kern$ objdump -h kernel

kernel: file format elf32-i386

Sections:

Idx Name Size VMA LMA File off Algn

0 .text 000019f1 f0100000 00100000 00001000 2**4

CONTENTS, ALLOC, LOAD, READONLY, CODE

1 .rodata 000007f0 f0101a00 00101a00 00002a00 2**5

CONTENTS, ALLOC, LOAD, READONLY, DATA

2 .stab 00004105 f01021f0 001021f0 000031f0 2**2

CONTENTS, ALLOC, LOAD, READONLY, DATA

3 .stabstr 00001be6 f01062f5 001062f5 000072f5 2**0

CONTENTS, ALLOC, LOAD, READONLY, DATA

4 .data 0000a300 f0108000 00108000 00009000 2**12

CONTENTS, ALLOC, LOAD, DATA

5 .bss 00000650 f0112300 00112300 00013300 2**5

ALLOC

6 .comment 00000034 00000000 00000000 00013300 2**0

CONTENTS, READONLY

mem_init 函数

这里需要用到 PageInfo 这个结构体了,首先在 inc/memlayout.h 中找到其定义:

struct PageInfo {

// Next page on the free list.

struct PageInfo *pp_link;

// pp_ref is the count of pointers (usually in page table entries)

// to this page, for pages allocated using page_alloc.

// Pages allocated at boot time using pmap.c's

// boot_alloc do not have valid reference count fields.

uint16_t pp_ref;

};

这是一个非常典型的链表。其中,pp_ref 表示有多少个指针指向该页,pp_link 表示空闲内存列表中的下一页。注意,非空闲页的 pp_link 总是为 NULL。

mem_init 函数中需要添加以下两行:

//

// Allocate an array of npages 'struct PageInfo's and store it in 'pages'.

// The kernel uses this array to keep track of physical pages: for

// each physical page, there is a corresponding struct PageInfo in this

// array. 'npages' is the number of physical pages in memory. Use memset

// to initialize all fields of each struct PageInfo to 0.

// Your code goes here:

pages = (struct PageInfo *) boot_alloc(npages * sizeof(struct PageInfo));

memset(pages, 0, npages * sizeof(struct PageInfo));

需要注意的是分配内存用的是 boot_alloc。这是一个仅用于 JOS 设置自身虚拟内存系统时使用的物理内存分配器,仅用于 mem_init 函数。当初始化页面以及空闲内存列表后,不再使用 boot_alloc,而使用 page_alloc。

page_init 函数

void

page_init(void)

{

// NB: DO NOT actually touch the physical memory corresponding to

// free pages!

size_t i;

// 1) Mark physical page 0 as in use.

// This way we preserve the real-mode IDT and BIOS structures

// in case we ever need them. (Currently we don't, but...)

pages[0].pp_ref = 1;

// 2) The rest of base memory, [PGSIZE, npages_basemem * PGSIZE)

// is free.

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) Then comes the IO hole [IOPHYSMEM, EXTPHYSMEM), which must

// never be allocated.

for (i = IOPHYSMEM/PGSIZE; i < EXTPHYSMEM/PGSIZE; i++) {

pages[i].pp_ref = 1;

}

// 4) Then extended memory [EXTPHYSMEM, ...).

// Some of it is in use, some is free. Where is the kernel

// in physical memory? Which pages are already in use for

// page tables and other data structures?

size_t first_free_address = PADDR(boot_alloc(0));

for (i = EXT

  • 0
    点赞
  • 1
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值