思考题
Thinking 6.1
应当如下修改:(仅贴出修改部分,即switch内的代码)
具体来说,交换父子部分的代码即可。
1 | switch (fork()) { |
Thinking 6.2
dup 函数的作用的作用是把一个文件描述符的内容映射给另一个文件描述符。
比如有一个管道,各个文件描述符映射次数为 p[0] = p[1] = 1,pipe = 2。
如果此时要映射读端,会先 p[0],再 pipe。
如果这两个操作之间发生中断,则会导致 p[0] == pipe。此时就会错误的认为写端关闭,出现错误。
Thinking 6.3
准确来说,MOS 通过关中断的方式让系统调用不被中断,因而对于用户而言,系统调用期间不会发生中断,可以被视为是原子的。
具体来说,代码里涉及到了两个宏,会将 CP0_STATUS 寄存器的 STATUS_CU0 位置位,从而实现开关中断的效果,而每次触发系统调用会首先调用相关宏关中断,结束后再开中断。
注:这种方式显然不适用于多核的情况,多核时需要采用硬件提供的操作来进行一些原子操作,或者使用互斥锁等方式保证进程同步。
Thinking 6.4
- 可以。我们通过验证 pageref(fd) == pager(pipe) 来检测管道是否关闭,如果改变上述解除映射顺序,就能一直保证 pageref(fd) < pageref(pipe),不会出现错误。
- 可以,通过先将 pageref(pipe)++ ,再将 pageref(fd)++的方式,保证了任何时候都有pageref(fd) < pageref(pipe),不会出现错误。
Thinking 6.5
- 打开文件的过程包括:用户调用用户库的 open() 函数,进而调用 fsipc_open() 函数向文件管理进程发送 ipc 请求,文件管理进程通过调用 serv_open() 进而调用相关函数,经过查找路径等过程将文件打开,存储文件描述符并通过 ipc 返回给用户。
- 打开 ELF 是通过 load_icode() 函数完成。函数中解析出每个段的段头 ph 和数据在内存中的起始位置 bin,再通过 elf_load_seg() 加载各个程序段,相关的内存拷贝和映射工作由 load_icode_mapper() 函数进行,通过调用相关的内存处理函数进行映射。
- 在 elf_load_seg() 函数中,先将 ELF 文件中已有的数据映射进内存,完成之后,还会继续调用 map_page() (即 load_icode_mapper() 函数),将全 0 的页面映射到后续的部分,使得大小能够与 ELF 中设置的大小匹配,保证了 .bss 中的变量也能有足够的空间,且初始化为 0 。
Thinking 6.6
在 usr/init.c 中,调用了 opencons() 函数,打开一个可读写的文件描述符 fd,由于此时并没有任何文件描述符被 alloc ,因此这是第一个即 0 号文件描述符。之后调用 dup(0, 1) 将 0 号复制到 1 号,从而实现了将其定为标准输入和标准输出。
Thinking 6.7
MOS 中的 shell 命令都是外部命令。
而 cd 命令需要改变当前的进程所在目录即 pwd,如果在外部更改,一旦 fork 了新进程,进程的所在目录会回到根目录下,不能实现正确的 cd 效果。因此在外部无法正确实现 cd,只能在内部实现。
Thinking 6.8
- 可以观察到两次 spawn,分别对应 ls 和 cat 两个命令。
- 可以观察到四次进程销毁,分别对应开始时执行命令 fork 出的子 shell 进程,ls 和 cat 两个命令以及管道 fork 出的子进程。
难点分析
- 本实验一方面的主要难点在于 pipe 相关函数的思维量,需要一点点思考来使代码能够适应不同初始情况下对管道信息的维护,主要是对读位置和写位置的处理等,需要全面覆盖到各种情况,因此不能马虎随便写。
- 此外关于管道关闭判断和 pageref 顺序导致的问题,已经在指导书和思考题中说明,并没有太高难度,主要是明确对中断的正确理解即可。
- 到 spawn 函数部分,则需要充分理解包括 lab2、lab3、lab4、lab5 中的相关知识,熟练使用相关系统调用和其他函数,然后按照提示进行补全即可。
- sh 部分,理解重定向的实现方式是通过映射到文件描述符 0 和 1 的原理,在此基础上调用 open 和 dup 等函数即可。
实验体会
Lab6 的完成,有一种为半个多学期的努力画上句点的感觉。在看到(虽然大多数代码都不是)自己写的操作系统终于能跑出一个像样的 shell 界面时,还是很有成就感的。相应的,Lab6 的相关内容也显得综合性较强,如果对前面的 Lab 有足够的了解其实实现起来相对轻松,但是如果知识有漏洞可能就不会那么顺利。
祝贺操作系统实验完结!