1. Part A: User Environments and Exception Handling
新的头文件inc/env.h
包含JOS中用户环境的基本定义。内核使用Env数据结构来跟踪每个用户环境。 在本实验中,最初只会创建一个环境,但您需要设计JOS内核以支持多个环境; lab4将通过允许用户环境fork
其他环境来利用此功能。
1.1. Exercise1-分配环境数组
Modify mem_init() in kern/pmap.c to allocate and map the envs array. This array consists of exactly NENV instances of the Env structure allocated much like how you allocated the pages array. Also like the pages array, the memory backing envs should also be mapped user read-only at UENVS (defined in inc/memlayout.h) so user processes can read from this array.
有了lab2的铺垫和理解,这个Exe就很容易做了。
// LAB 3: Your code here.
envs = (struct Env*)boot_alloc(sizeof(struct Env)*NENV);
memset(envs, 0, sizeof(struct Env)*NENV);
// LAB 3: Your code here.
boot_map_region(kern_pgdir,
UENVS,
ROUNDUP((sizeof(struct Env)*NENV), PGSIZE),
PADDR(envs),
PTE_U);
1.2. 创建和运行环境(进程)
在这里,环境和进程是可以对等的,都指程序运行期间的抽象。不直接叫进程是因为jos中实现的系统调用和UNIX是有差别的。
我们需要编写运行用户环境所需的kern/env.c
代码。 因为我们还没有文件系统,所以我们将设置内核来加载嵌入在内核中的静态二进制映像。JOS将此二进制文件作为ELF可执行映像嵌入内核中。
在kern/Makefrag
文件中,你会发现一些魔法将这些二进制文件直接“链接”到内核可执行文件中,就好像它们是.o文件一样。 链接器命令行上的-b binary
选项会将这些文件作为“原始”未解释的二进制文件链接,而不是作为编译器生成的常规.o文件链接。(就链接器而言,这些文件根本不必是ELF文件——它们可以是任何格式,例如文本文件或图片)如果在构建内核后查看obj/kern/kernel.sym
, 你会注意到链接器“神奇地”产生了许多有趣的符号,这些符号具有晦涩的名字,如_binary_obj_user_hello_start,_binary_obj_user_hello_end和_binary_obj_user_hello_size。 链接器通过修改二进制文件的文件名来生成这些符号名称; 这些符号为常规内核代码提供了引用嵌入式二进制文件的方法。
1.3. Exercise 2
in the file env.c, finish coding the following functions:
- env_init()
- env_setup_vm()
- region_alloc()
- load_icode()
- env_create()
- env_run()
1.3.1. env_init()
void
env_init(void)
{
// Set up envs array
// LAB 3: Your code here.
int i;
// 确保最小的env在最前端
for (i = NENV-1; i >= 0; --i) {
envs[i].env_id = 0;
envs[i].env_link = env_free_list;
env_free_list = &envs[i];
}
// Per-CPU part of the initialization
env_init