BUAA-OS-lab2
lab2的名字叫内存管理,内容大致可以分为物理内存管理、虚拟内存管理和TLB管理。上机主要考察前两个,指导书在此基础上还介绍了一些相关概念。
相关概念
访存流程
软件访存的虚拟地址会先被 MMU 硬件映射到物理地址,随后使用物理地址来访问内存或其他外设。其中 kseg0 和 kseg1 段可以直接映射到内存某段上,方法是把高两位清0。
内存初始化
其实这一块的官方名字是内核程序启动,但lab2代码只实现了其中关于内存的部分,所以这里就把它简化成内存初始化。
内核启动函数 mips_init 在lab2时调用了三个跟内存有关的函数:
mips_detect_memory(ram_low_size)以页为单位探测硬件可用内存,memsize / PAGE_SIZE的小巧思。mips_vm_init()将上面可用内存以页为单位管理起来,建立虚拟页框,或者说struct Page结构体,和物理内存的对应关系。page_init()开始用宏操作struct Page结构体,把内核已经分配了的内存的struct Page的pp_ref标记为1,没被分配的内存的struct Page的pp_ref标记为0,塞进page_free_list这个空闲页链表中。
物理内存管理
或者叫做链表宏的使用。
链表宏一览
LIST_HEAD(name, type)存储了struct type*的第一个链表块的struct name结构体LIST_ENTRY(type)用于实现struct type类型的链表的struct {}结构体LIST_EMPTY(head)用于判断链表是否为空,head为结构体指针LIST_FIRST(head)获取链表的第一个链表块LIST_FOREACH(var, head, field)var是struct type*类型的指针,head为结构体指针,field为LIST_ENTRY(type)类型LIST_INIT(head)设置head首地址存储的第一个元素为NULLLIST_INSERT_AFTER(listelm, elm, field)LIST_INSERT_BEFORE(listelm, elm, field)LIST_INSERT_HEAD(head, elm, field)其中
listelm和elm是同类型,field是其中LIST_ENTRY(type)类型变量LIST_REMOVE(elm, field)发现可以不知道前后元素,直接删除
发现如果用LIST_INSERT_HEAD 、LIST_REMOVE(elm, field) 和 LIST_FIRST(head) 就可以实现栈操作
其他内存操作函数
int page_alloc(struct Page **new)从空闲列表中分配一个页面出去,用new返回指针,函数返回值为0表明操作成功void page_decref(struct Page *pp)