练习0
填写已有实验
本实验依赖实验1.请把要做的实验1的代码填入本实验中代码有lab1的注释相应部分
首先利用meld工具比较两个文件的差异
发现缺失的是kdebug.c、trap.c
两个文件的相关代码,补全后进行下一练习
首先运行
报错,看来就是需要进行实验的所有编程才能完整的运行
练习1
实现firstfit连续物理内存分配算法(需要编程)
在实现firstfit内存分配算法的回首函数时,要考虑地址连续的空闲块之间的合并操作
在实验前先仔细学习一下firstfit算法
原理
要求空闲分区链以地址递增的次序链接。在分配内存时,从链首开始顺序查找,直至找到一个大小能满足要求的分区为止;然后再按照作业的大小,从该分取中划出一块内存空间分配给请求者,余下的空闲分区仍留在空闲链中。若从链首直到链尾都不能找到一个能满足要求的分区,则此次内存分配失败,返回。该算法倾向于优先利用内存中低地址部分的空闲分区,从而保留了高址部分的大空闲区。这给为以后到达的大作业分配大的内存空间创造了条件,其缺点是低址部分不断被划分,会留下许多难以利用的、很小的空闲分区,而每次查找又都是从低址部分开始,这无疑会增加查找可用空闲分区时的开销。
大致流程图
为了与以后的分页机制配合,首先需要建立对整个计算机的每一个物理页的属性,用结构体Page来表示,它包含了映射此物理页的虚拟页个数,描述物理页属性的flags和双向链接各个Page结构的page_link双向链表。
struct Page{
int ref;
uint32_t flags;
unsigned int property;
list_entry_t page_link;
}
ref
表示该页被页表的引用记数。如果这个页被页表引用了,即在某页表中有一个页表项设置一个虚拟页到这个Page管理的物理页的映射关系,就会把Page的ref加一。反之,若页表项取消,即映射关系解除,就减一。
flags
表示此物理页的状态标记,有两种属性,bit 0表示是否被保留,如果被保留了则设为1,且不能放到空闲页链表中,即这样的页不是空闲页,不能动态分配与释放。比如内核代码占用的空间。bit 1表示此页是否是空闲的。如果设置为1,表示这页是空闲的,可以被分配;如果设置为0,表示这页已经被分配出去了,不能被再二次分配。
property
用来记录某连续内存空闲块的大小(即地址连续的空闲页的个数)。这里需要注意的是用到此成员变量的这个Page比较特殊,是连续内存空闲地址最小的一夜(即第一页)。
page_link
是便于把多个连续内存空闲块链接在一起的双向链表指针,连续内存空闲块利用这个页的成员变量page_link来链接比它地址小和大的其他连续内存空闲块
为了有效的管理这些小连续内存空闲块,所有的连续内存空闲块可用一个双向链表来管理,便于分配和释放,为此定义一个free_area_t
typedef struct {
list_entry_t free_list; // the list header
unsigned int nr_free; // number of free pages in this free list
} free_area_t;
free_list
是一个list_entry结构的双向链表指针nr_free
则记录当前空闲页的个数
有了这两个数据结构,就可以管理起来整个以页尾单位的物理内存空间
理解完原理,开始进行实验
首先根据实验指导书,我们第一个实验需要完成的主要是default_pmm.c
中的default_init
,default_init_memmap
,default_alloc_pages
, default_free_pages
几个函数的修改。
一些标志的定义:
default_init
static void
default_init(void) {
list_init(&free_list);
nr_free = 0;
}
看下注释
(2) default_init: you can reuse the demo default_init fun to init the free_list and set nr_free to 0.
free_list is used to record the free mem blocks. nr_free is the total number for free mem blocks.
根据注释代码已经完成无需改动
default_init_memmap
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 = p->property = 0;
set_page_ref(p, 0);
}
base->property = n;
SetPageProperty(base);
nr_free += n;
list_add(&free_list, &(base->page_link));
}
查看一下注释
* (3) default_init_memmap: CALL GRAPH: kern_init --> pmm_init-->page_init-->init_memmap--> pmm_manager->init_memmap
* This fun is used to init a free block (with parameter: addr_base, page_number).
* First you should init each page (in memlayout.h) in this free block, include:
* p->flags should be set bit PG_property (means this page is valid. In pmm_init fun (in pmm.c),
* the bit PG_reserved is setted in p->flags)
* if this page is free <