BUAA_OS_lab6
BUAA_OS_lab6学习日记
Thinking
Thinking 6.1
示例代码中,父进程操作管道的写端,子进程操作管道的读端。如果现在想 让父进程作为“读者”,代码应当如何修改?
父进程更改写端1,子进程更改读端0。
Thinking 6.2
上面这种不同步修改 pp_ref 而导致的进程竞争问题在 user/lib/fd.c 中 的dup 函数中也存在。请结合代码模仿上述情景,分析一下我们的 dup函数中为什么会出 现预想之外的情况
两个相关的页面map或者unmap的之间发生了时钟中断,会导致不一致的现象。
Thinking 6.3
阅读上述材料并思考:为什么系统调用一定是原子操作呢?如果你觉得不是 所有的系统调用都是原子操作,请给出反例。希望能结合相关代码进行分析说明。
系统调用一定是原子操作,进程切换是通过定时器产生时钟中断,触发时钟中断切换进程。但是syscall跳转到内核态时,CPU将SR寄存其的IE位置0,关闭了时钟中断。
Thinking 6.4
仔细阅读上面这段话,并思考下列问题
- 按照上述说法控制 pipe_close中 fd和 pipeunmap的顺序,是否可以解决上述场 景的进程竞争问题?给出你的分析过程。
- 我们只分析了 close时的情形,在 fd.c中有一个 dup函数,用于复制文件描述符。 试想,如果要复制的文件描述符指向一个管道,那么是否会出现与 close类似的问 题?请模仿上述材料写写你的理解
当对于pipe页面的引用次数小于对两个fd的和的时候,就会出现安全问题,而只要先解除fd再解除pipe,就不会出现上述问题,问题也仅仅只是拉大了二者的差距而已,对于结果没有影响。
会出现pipe页面的引用次数小于对两个fd的和的问题
Thinking 6.5
- 认真回看Lab5文件系统相关代码,弄清打开文件的过程。
- 回顾Lab1与Lab3,思考如何读取并加载ELF文件。
- 在Lab1 中我们介绍了 data text bss 段及它们的含义,data 段存放初始化过的全 局变量,bss段存放未初始化的全局变量。关于memsize和filesize,我们在Note 1.3.4中也解释了它们的含义与特点。关于Note1.3.4,注意其中关于“bss段并不在文 件中占数据”表述的含义。回顾Lab3并思考:elf_load_seg()和load_icode_mapper() 函数是如何确保加载ELF文件时,bss段数据被正确加载进虚拟内存空间。bss段 在ELF中并不占空间,但ELF加载进内存后,bss段的数据占据了空间,并且初始 值都是0。请回顾elf_load_seg() 和 load_icode_mapper() 的实现,思考这一点 是如何实现的?
下面给出一些对于上述问题的提示,以便大家更好地把握加载内核进程和加载用户进程的 区别与联系,类比完成 spawn函数。
关于第一个问题,在Lab3中我们创建进程,并且通过 ENV_CREATE(…) 在内核态加 载了初始进程,而我们的 spawn函数则是通过和文件系统交互,取得文件描述块,进而找 到ELF 在“硬盘”中的位置,进而读取。 关于第二个问题,各位已经在Lab3中填写了load_icode 函数,实现了ELF 可执行 文件中读取数据并加载到内存空间,其中通过调用elf_load_seg 函数来加载各个程序段。 在Lab3 中我们要填写 load_icode_mapper 回调函数,在内核态下加载 ELF 数据到内存 空间;相应地,在Lab6中spawn函数也需要在用户态下使用系统调用为ELF数据分配空 间。
- 在 Lab3 中我们创建进程,并且通过 ENV_CREATE(…) 在内核态加载了初始进程,而我们的 spawn 函数则是通过和文件系统交互,取得文件描述块,进而找到 ELF 在“硬盘”中的位置,进而读取。
- 在 Lab3 中填写的 load_icode 函数,实现了 ELF 可执行文件中读取数据并加载到内存空间,其中通过调用 elf_load_seg 函数来加载各个程序段。在 Lab3 中我们要填写 load_icode_mapper 回调函数,在内核态下加载 ELF 数据到内存空间;相应地,在 Lab6 中 spawn 函数也需要在用户态下使用系统调用为 ELF 数据分配空间。
- bss段应该与text段data段连续的放在一起,但是ELF中没有空间,在分配映射页面时,text段与data段没有占满的空间置为0给了bss段,然后再给他另外分配的时候,只使用syscall_mem_alloc而不映射
Thinking 6.6
通过阅读代码空白段的注释我们知道,将标准输入或输出定向到文件,需要 我们将其dup到0或1号文件描述符(fd)。那么问题来了:在哪步,0和1被“安排”为 标准输入和标准输出?请分析代码执行流程,给出答案
在user/init.c中
1 |
|
Thinking 6.7
在 shell 中执行的命令分为内置命令和外部命令。在执行内置命令时shell不 需要fork 一个子 shell,如 Linux 系统中的 cd 命令。在执行外部命令时 shell 需要 fork 一个子shell,然后子 shell 去执行这条命令。 据此判断,在MOS 中我们用到的 shell 命令是内置命令还是外部命令?请思考为什么 Linux 的 cd 命令是内部命令而不是外部命令?
- 外部命令
- 内部命令
Thinking 6.8
在你的 shell 中输入命令 ls.b | cat.b > motd。
- 请问你可以在你的shell 中观察到几次spawn?分别对应哪个进程?
- 请问你可以在你的shell 中观察到几次进程销毁?分别对应哪个进程?
答案:
- 有两次spawn,分别打开了ls.b,cat.b进程
- 有四个进程的销毁,分别是左指令的执行进程,右指令的执行进程,spawn打开的两个执行进程。
实验感想和总结
lab6 总体的实验难度不难,函数也比较少,但是可以说是和我们日常最贴近的一次lab,通过实验,我们实现了shell的一些简单功能。