操作系统 OS Lab4 学习笔记
今天的内容是OS Lab4的学习复习笔记……这周的OO强测只拿了20分,之前的所有优化努力直接白给……蓝瘦。
所以OS不能再一知半解了,在一开始同样放下学长博客与课程指导中心的视频——
https://www.cnblogs.com/SivilTaram/p/os_lab4.html
https://www.cnblogs.com/sharinka0715/p/10776860.html
https://ausar.xyz/index.php/archives/77/
https://www.cnblogs.com/Yzx835/p/10775984.html
https://blog.csdn.net/qq_36740940/article/details/89523911
https://blog.csdn.net/weixin_44689094/article/details/105893744
https://blog.csdn.net/weixin_41412192/article/details/89522232
在这一节的实验中,我们需要实现系统调用机制,并在此基础上实现进程间通信(IPC)机制和一个重要的系统调用fork。在梳理博客的时候,有的学长是根据运行顺序来总结的,我目前还是先跟着题目走。
系统调用
系统调用的流程:
- 调用一个封装好的用户空间的库函数(如writef)
- 调用用户空间的syscall_* 函数
- 调用msyscall,用于陷入内核态
- 陷入内核,内核取得信息,执行对应的内核空间的系统调用函数(sys_*)
- 执行系统调用,并返回用户态,同时将返回值“传递”回用户态
- 从库函数返回,回到用户程序调用处
Exercise 4.1
填写user/syscall_wrap.S 中的msyscall 函数,使得用户部分的系统调用机制可以正常工作。
LEAF(msyscall)
// TODO: you JUST need to execute a `syscall` instruction and return from msyscall
syscall
jr ra
nop
END(msyscall)
执行syscall指令,然后从函数返回。
Thinking 4.1
思考并回答下面的问题:
- 内核在保存现场的时候是如何避免破坏通用寄存器的?
- 系统陷入内核调用后可以直接从当时的a3 参数寄存器中得到用户调用msyscall 留下的信息吗?
- 我们是怎么做到让sys 开头的函数“认为”我们提供了和用户调用msyscall 时同样的参数的?
- 内核处理系统调用的过程对Trapframe 做了哪些更改?这种修改对应的用户态的变化是?
Exercise 4.2
按照lib/syscall.S 中的提示,完成handle_sys 函数,使得内核部分的系统调用机制可以正常工作。
在通过特权指令syscall 陷入内核态后,处理器将PC 寄存器指向一个相同的内核异常入口。在trap_init 函数中将系统调用类型的异常的入口设置为了handle_sys 函数。
第一个TODO,MIPS有异常程序计数器(exception program counter,EPC),属于CP0寄存器,用于保存造成异常的那条指令的地址。让EPC值+4到下一条指令,这样就不会陷入反复中断的死循环之中。
/*** exercise 4.2 ***/
NESTED(handle_sys,TF_SIZE, sp) // 把用户态的所有寄存器存进栈帧,sp相当于栈顶
SAVE_ALL // 用于保存所有寄存器的汇编宏
CLI // 用于屏蔽中断位的设置的汇编宏
nop
.set at // 恢复$at寄存器的使用
// TODO: Fetch EPC from Trapframe, calculate a proper value and store it back to trapframe.
lw t0, TF_EPC(sp) // 将Trapframe的EPC寄存器取出
addu t0, 4 // 计算一个合理的值
sw t0, TF_EPC(sp) // 存回Trapframe中