LAB5: Spawning Processes
前言
记录一下自己的学习过程
实验内容翻译:
https://gitee.com/cherrydance/mit6.828
该翻译仅供参考
练习7
spawn依赖于新的系统调用sys_env_set_trapframe来初始化新创建环境的状态。在kern/syscall.c中实现sys_env_set_trapframe(不要忘记在syscall()中分派新的系统调用)。
通过运行kern/init.c中的user/spawnhello程序来测试你的代码,该程序将尝试从文件系统中生成/hello。
使用make grade来测试你的代码。
struct Env* env_store;
if(envid2env(envid, &env_store, 1) < 0){
return -E_BAD_ENV;
}
//判断tf的地址是否有效
user_mem_assert(env_store, tf, sizeof(struct Trapframe), PTE_U);
env_store->env_tf = *tf;
//设置IOPL为0
env_store->env_tf.tf_eflags &= (~FL_IOPL_MASK);
//将代码段的特权级别(CPL)设置为3,即用户态特权级别。
env_store->env_tf.tf_cs |= 3;
//设置中断
env_store->env_tf.tf_eflags |= FL_IF;
return 0;
之后在syscall设置系统调用,运行结果如下:
练习8
修改lib/fork.c中的duppage函数,遵循新的约定。如果页表项设置了PTE_SHARE位,就直接复制映射。(你应该使用PTE_SYSCALL而不是0xfff来屏蔽页表项中的相关位。0xfff还会包括访问和脏位。)
同样地,在lib/spawn.c中实现copy_shared_pages函数。它应该遍历当前进程的所有页表项(就像fork所做的那样),将设置了PTE_SHARE位的任何页映射复制到子进程中。
duppage函数:
加一个对PTE_SHARE的判断
if(uvpt[pn] & PTE_SHARE){
if(sys_page_map(0, (void *)(pn * PGSIZE), envid, (void *)(pn * PGSIZE), uvpt[pn] & PTE_SYSCALL)){
panic("duppage: sys_page_map failure");
}
}
copy_shared_pages函数:
int i, ret;
for (i = 0; i< PGNUM(USTACKTOP); ++i) {
if ( (uvpd[i >> 10] & PTE_P) && (uvpt[i] & PTE_P) ) {
if (uvpt[i] & PTE_SHARE) {
if ( (ret = sys_page_map(thisenv->env_id, (void *)(i*PGSIZE), child, (void *)(i*PGSIZE), uvpt[i] & PTE_SYSCALL )) < 0)
return ret;
}
}
}
return 0;
遍历所有的页表项,如果该页表项的PTE_SHARE被设置了,则将该页面映射到child的地址空间。
make run-testpteshare 运行结果:
make run-testfdsharing 运行结果:
练习9
在你的kern/trap.c中,调用kbd_intr来处理trap IRQ_OFFSET+IRQ_KBD,并调用serial_intr来处理trap IRQ_OFFSET+IRQ_SERIAL。
if(tf->tf_trapno == IRQ_OFFSET + IRQ_KBD){
lapic_eoi();
kbd_intr();
return;
}
if(tf->tf_trapno == IRQ_OFFSET + IRQ_SERIAL){
lapic_eoi();
serial_intr();
return;
}
运行结果:
练习10
Shell不支持I/O重定向。我们希望能够运行sh <脚本,而不必手动输入脚本中的所有命令,就像你之前所做的那样。在user/sh.c中添加<的I/O重定向功能。
通过在shell中输入sh <脚本来测试你的实现。
运行make run-testshell来测试你的shell。testshell会将上述命令(也可以在fs/testshell.sh中找到)输入到shell中,然后检查输出是否与fs/testshell.key匹配。
if ((fd = open(t, O_RDONLY)) < 0) {
cprintf("open %s for write: %e", t, fd);
exit();
}
if (fd != 0){
dup(fd, 0); // 0 - 标准输入
close(fd);
}
总结
终于完成了最后一小部分