实验完善代码 LAB2-4下载链接 提取码:79t8
1、内核地址空间
JOS 将32位线性地址虚拟空间分为两部分,其中用户环境(用户进程)通常占据低地址部分,叫做用户地址空间;操作系统内核总是占据高位,叫做内核地址空间。这两部分的分界线是定义在memlayout.c 中的一个宏ULIM。JOS 为内核保留了256MB 的虚拟地址空间[0xF0000000,0xFFFFFFFF],这也解释了为什么在LAB1 我们设置的KERNBASE 是0xF0000000,否则的话用户地址空间将不够用。
2、权限及错误隔离
由于内核和用户进程只能访问各自的地址空间,所以我们必须在X86 页表中使用访问权限位来使用户进程的代码只能访问用户地址空间,而不会访问内核地址空间。否则,用户代码的一些错误可能会覆盖内核中的数据,最终导致内核崩溃。
处在用户地址空间中的代码不能访问高于ULIM 的地址空间,但是内核可以读写这部分的地址。需要注意的是,对于地址空间[UTOP, ULIM ] 内核和用户拥有同样的权限:只能读不能写; 这个范围的空间通常被用于将一些只读的内核数据结构暴露给用户。在UTOP之下的地址范围是给用户进程使用的,用户进程可以访问、修改 [0X0, UTOP] 地址空间的内容。
接下来的实验主要是设置UTOP 之上的地址空间:这也就是整个虚拟地址空间中的内核地址空间部分。
3、Exercise 5
//
// Now we set up virtual memory
//
// Map 'pages' read-only by the user at linear address UPAGES
// Permissions:
// - the new image at UPAGES -- kernel R, user R
// (ie. perm = PTE_U | PTE_P)
// - pages itself -- kernel RW, user NONE
// Your code goes here:
boot_map_region(kern_pgdir,UPAGES,PTSIZE,PADDR(pages),PTE_U);
//
// Use the physical memory that 'bootstack' refers to as the kernel
// stack. The kernel stack grows down from virtual address KSTACKTOP.
// We consider the entire range from [KSTACKTOP-PTSIZE, KSTACKTOP)
// to be the kernel stack, but break this into two pieces:
// * [KSTACKTOP-KSTKSIZE, KSTACKTOP) -- backed by physical memory //由物理内存支持
// * [KSTACKTOP-PTSIZE, KSTACKTOP-KSTKSIZE) -- not backed; so if
// the kernel overflows its stack, it will fault rather than
// overwrite memory. Known as a "guard page".
// Permissions: kernel RW, user NONE
// Your code goes here:
boot_map_region(kern_pgdir,KSTACKTOP-KSTKSIZE,KSTKSIZE,PADDR(bootstack),PTE_W);
//
// Map all of physical memory at KERNBASE.
// Ie. the VA range [KERNBASE, 2^32) should map to
// the PA range [0, 2^32 - KERNBASE)
// We might not have 2^32 - KERNBASE bytes of physical memory, but
// we just set up the mapping anyway.
// Permissions: kernel RW, user NONE
// Your code goes here:
//boot_map_region(pde_t *pgdir, uintptr_t va, size_t size, physaddr_t pa, int perm)
boot_map_region(kern_pgdir, KERNBASE, 0x10000000, 0x0, PTE_W);
// Check that the initial page directory has been set up correctly.
check_kern_pgdir();
4、Question
- 到目前为止页目录表中已经包含多少有效页目录项?他们都映射在哪里?
kern_pgdir ,实际的物理地址是 0xef400000 ,在页目录的第0x3BD项中;
pages 页面,实际的物理地址是0xef000000,在页目录的第0x3BC 项中;
[KSTACKTOP-KSTKSIZE,KSTKSIZE] 内核堆栈,实际的物理地址是[0xf0000000 - KSTKSIZE , 0xf0000000] ,在页目录的第0x3BF项中;
- 我们将内核和用户放在同一个地址空间,为什么用户程序不会读取内核空间?用什么机制保护内核空间?
用户程序读写内核空间可能会造成程序的崩溃, 正常的操作系统中采用的是段机制来保护内核空间的,但是JOS实验中只有一个段,用分页机制来实现的保护。
- 我们实验的操作系统的最大物理内存是多少?为什么?
从实验的代码以及上面的内存空间分布图可以知道,这个操作系统利用一个大小为4MB 的空间 [0xef000000, 0xef400000] 来存储页面信息,根据源码中PageInfo 结构可知该结构的大小为8B ,因此4MB 的空间可以存储的页面信息的个数为 4MB / 8B = 1/2 M (个),每个页面对应的物理空间为4KB,因此总的物理内存为 1/2 M * 4KB = 2GB。
- 如果现在的物理内存页达到最大个数,那么管理这些内存所需要的额外开销为多少?、
首先需要一个页目录,所占空间为4KB;其次需要1KB 个 页表,每个页表所占的空间为4KB,总的页表空间为4MB。因此总的空间大小为 4MB + 4KB 。
自此,LAB2 的Exercise 基本已经全部完成。
本文参考文章 http://grid.hust.edu.cn/zyshao/OSEngineering.htm
推荐这位博主系列的文章