Exercise 5.1

设置一下 e->env_tf.tf_eflags 就好了,对应的权限的宏的定义在 mmu.h 里面。

Do you have to do anything else to ensure that this I/O privilege setting is saved and restored properly when you subsequently switch from one environment to another? Why?

并不需要,因为在中断的时候 EFLAGS 会和其他寄存器一样被备份起来(trapentry.S), 然后恢复执行的时候再被还原回来(env.c:env_pop_tf)。

Exercise 5.2

JOS 把 0x10000000 ~ 0xD0000000DISKMAP ~ DISKMAP+DISKMAX 的地址空间作为磁盘的映射。 在这个空间内如果触发了 page fault,那就从内存分配一个 page, 然后读一个 block 到这个 page 中(JOS 中为了方便 PGSIZE == BLKSIZE == 4kb)。 当程序写数据的时候,CPU会自动把对应的页表项的 dirty 位标记上。 要把数据写回磁盘,则是通过定期的 flush 操作。 flush_block 检查一个 block 对应的页表项是否是 dirty,如果是的话,就写回磁盘的对应位置去。

理解了这个思路,按着 hints 写就好了。

Exercise 5.3

就是位运算。照着 hints 写就好了。

Exercise 5.4

照着 hints 写就好了。

Exercise 5.5

JOS 里面所有的文件系统操作都由一个特殊的用户态程序 FS 执行。 其他进程因为没有操作IO的能力(EFLAGS 里面不允许 IO 中断), 所以只能通过和 FS 进行通信来实现IO操作。

JOS 的 IPC 可以传递一个32位信息,外加可以设置共享一个页。 在文件系统相关的 IPC 中,调用者把操作类型当作32位整数传出去, 然后与 FS 共享一个 union Fsipc,这里面可以包含额外的请求信息。 FS 在收到请求后,把相应的结果写到这个 union Fsipc 里面, 另外还可以传回一个32位的返回值。

理解了这个思路,照着 hints 写就好了。

Exercise 5.6

这里 devfile_write 要注意一下写入的字节数不能大于 block 大小。

Exercise 5.7

注意要检查用户给定的内存是合法的,有一个函数可以调用 user_mem_assert。 另外,这里要除了在 tf_cs 里面设置 DPL 以外, 还要记得在 tf_eflags 启用中断,否则就无法被抢占了。

Exercise 5.8

duppage 的修改照着上个 lab 的上下文改一改就好了。 copy_shared_pages 照着 fork.c:fork 改一改就好了。

Exercise 5.9

trap.c:trap_dispatch 里面再加两项就好了。

Exercise 5.10

把下面的 Output redirection 稍微复制粘贴修改一下就好了。