BUAA-OS-lab2

Dawn

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 Pagepp_ref 标记为1,没被分配的内存的 struct Pagepp_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) varstruct type* 类型的指针,head 为结构体指针,fieldLIST_ENTRY(type) 类型

  • LIST_INIT(head) 设置 head 首地址存储的第一个元素为NULL

  • LIST_INSERT_AFTER(listelm, elm, field)

    LIST_INSERT_BEFORE(listelm, elm, field)

    LIST_INSERT_HEAD(head, elm, field)

    其中 listelmelm 是同类型,field 是其中LIST_ENTRY(type) 类型变量

  • LIST_REMOVE(elm, field) 发现可以不知道前后元素,直接删除

发现如果用LIST_INSERT_HEADLIST_REMOVE(elm, field)LIST_FIRST(head) 就可以实现栈操作

其他内存操作函数

  • int page_alloc(struct Page **new) 从空闲列表中分配一个页面出去,用 new 返回指针,函数返回值为0表明操作成功
  • void page_decref(struct Page *pp)
Comments