前言

lab5比较简单，相对于之前的lab来说。主要就是完成简单的文件系统。大部分代码mit都已经帮你搭好了。

Exercise 1

i386_init identifies the file system environment by passing the type ENV_TYPE_FS to your environment creation function, env_create. Modify env_create in env.c, so that it gives the file system environment I/O privilege, but never gives that privilege to any other environment

Question 1

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?

Exercise 2

Implement the bc_pgfault and flush_block functions in fs/bc.c. bc_pgfault is a page fault handler, just like the one your wrote in the previous lab for copy-on-write fork, except that its job is to load pages in from the disk in response to a page fault. When writing this, keep in mind that (1) addr may not be aligned to a block boundary and (2) ide_read operates in sectors, not blocks.

bc_pgfault 当产生page fault，说明这一页还未读取到内存中，则先分配一页，然后进行读取。

flush_block 内存中的内容被修改之后，需要写回到磁盘中。因为本质上它就是一块Cache

Exercise 3

Use free_block as a model to implement alloc_block in fs/fs.c, which should find a free disk block in the bitmap, mark it used, and return the number of that block. When you allocate a block, you should immediately flush the changed bitmap block to disk with flush_block, to help file system consistency.

Josbitmap来跟踪空闲块，这里比较简单，模仿block_is_free写即可。

Exercise 4

Implement file_block_walk and file_get_block. file_block_walk maps from a block offset within a file to the pointer for that block in the struct File or the indirect block, very much like what pgdir_walk did for page tables. file_get_block goes one step further and maps to the actual disk block, allocating a new one if necessary.

file_block_walk查找文件的磁盘块。分为两种情况，一种是direct blocks，也就是前十个块，是直接存在File数据结构中的，而indirect block，是一个指针指向额外的数组。

file_get_block 是对file_block_walk的调用。

Exercise 5

Implement serve_read in fs/serv.c。

serve_read没什么难度。

Exercise 6

Implement serve_write in fs/serv.c and devfile_write in lib/file.c.

serve_write 参照着serve_read写就行。

devfile_write也一样。注意fsipcbuf是存放各种读写操作的联合体。

Exercise 7

spawn relies on the new syscall sys_env_set_trapframe to initialize the state of the newly created environment. Implement sys_env_set_trapframe in kern/syscall.c(don’t forget to dispatch the new system call in syscall()).

1. 打开文件，获取Fd
2. 读取ELF头，这一步和load_icode，只不过这里是从磁盘中读
3. 创建子进程
4. 把子进程的eip设置到程序的入口点
5. 初始化栈
6. 把所有需要加载的程序段加载到子程序的地址空间。到这里，文件操作完毕。
7. 初始化进程状态

sys_env_set_trapframe很简单

Exercise 8

Change duppage in lib/fork.c to follow the new convention. If the page table entry has the PTE_SHARE bit set, just copy the mapping directly. (You should usePTE_SYSCALL, not 0xfff, to mask out the relevant bits from the page table entry. 0xfff picks up the accessed and dirty bits as well.)

Likewise, implement copy_shared_pages in lib/spawn.c. It should loop through all page table entries in the current process (just like fork did), copying any page mappings that have the PTE_SHARE bit set into the child process.

duppage

copy_shared_pages

Exercise 9

In your kern/trap.c, call kbd_intr to handle trap IRQ_OFFSET+IRQ_KBD and serial_intr to handle trap IRQ_OFFSET+IRQ_SERIAL.

Exercise 10

The shell doesn’t support I/O redirection. It would be nice to run sh <script instead of having to type in all the commands in the script by hand, as you did above. Add I/O redirection for < to user/sh.c.