6.828 Lab2: Memory management
Exercise 2.1
这题开始自己实现内存分配了。站在内核层面来分配内存和站在用户角度来分配内存,感觉还是很不一样的。
这题还是很简单的,就是在实现 page_init
的时候折腾了一下,其实提示很清楚:
Where is the kernel in physical memory? Which pages are already in use for page tables and other data structures?
linker 的设置里面把 EXTPHYSMEM
丢到了 end
这么个地方,也就是实现 boot_alloc()
的时候的起始位置。调用 boot_alloc(0)
可以知道内核的内存占用到了哪里。然后就是找一找头文件,可以发现一些好用的小工具宏 PGNUM()
以及 PADDR()
。
Exercise 2.4
这题卡了我好久,一是因为对 JOS 的代码不熟悉;二是因为没仔细看 x86 的说明,没看到 page directory 把 page table 的地址存在哪里了;三是因为没有正确理解 pde_t
和 pte_t
这两个类型名。
- 在 x86 里面,linear address 可以从高到低拆成三部分:10位
dir
,10位page
,还有剩下的12位offset
。 - 页表分成两级,第一级叫做 page directory,第二级叫做 page table。
- page directory 里面每一行叫做 page directory entry,page table 里面的每一行叫做 page table entry。两者具有相同的结构。
- 两者都是32位,具有相同的结构。
- 低12位是设置位,包括了
P
是否可用;R/W
只读或者可写;U/S
用户或者只有操作系统可用;还有一些其他的东西。 - 对 page table entry 来说,高20位是当前虚拟地址要映射过去的物理地址。
- 对 page directory entry 来说,高20位是 page table 的地址。注意到页大小是4KB,一个 page table 正好需要一个页来存放,所以只要知道高20位就行了。
- 当前的 page directory 地址放在在
CR3
里面。
在 JOS 里面,pde_t
和 pte_t
这两者都是 uint32_t
,并且在代码里面频繁出现 pde_t*
和 pte_t*
。我总结了一下,按照这么想就很好理解了:
pde_t
就是一条 page directory entrypte_t
就是一条 page table entrypde_t*
可以是某条 page directory entry 的指针,也可以是pde_t[]
即整个 page directorypte_t*
可以是某条 page table entry 的指针,也可以是pte_t[]
即整个 page table
现在怎么看着这么简单但是一开始做的时候就卡住了呢(迷)?
Exercise 1.5
这题就非常非常水了,写几个 boot_map_region()
就好了。
Challenges
关于这个 PTE_PS
,在 Intel x86 手册第三卷的3-32即114页可以看到:
Page size (PS) flag, bit 7 page-directory entries for 4-KByte pages Determines the page size. When this flag is clear, the page size is 4 KBytes and the page-directory entry points to a page table. When the flag is set, the page size is 4 MBytes for normal 32-bit addressing (and 2 MBytes if extended physical addressing is enabled) and the page- directory entry points to a page. If the page-directory entry points to a page table, all the pages associated with that page table will be 4-KByte pages.
也就是说现在的 x86 支持两种 page size: 4KB/4MB。这个位如果是1,那么这条 page directory entry 相当于 4MB-page table entry,否则就是一个指向 4KB-page table 的指针。不过具体的就懒得改了。