lab4实验报告
一、实验思考题
Thinking4.1
保存现场过程中改写非通用的寄存器,SAVE_ALL
将所有通用寄存器的值存入栈中。一些其他的寄存器,如k0
存储sp
的值,k1
存储帮助sp
更新值,v0
存储部分非通用寄存器相关的值。所以可以避免破坏通用寄存器。
可以直接获取,在处理相关系统调用时,a0-a3
的值还没有改变。
在调用sys
相关的函数时,通过将前4个参数赋值给对应的寄存器上,后续参数保存在栈中的对应位置。
修改epc
的值以便返回时可以继续执行下一条指令,将执行结果返回值存入v0
寄存器,从系统调用返回时,用户态获取系统调用的返回值,并且可以继续执行下一条指令。
Thinking4.2
- 子进程和父进程之间共享代码段,并且具有相同的数据和状态,所以子进程和父进程的代码段是一样的
- 子进程恢复上下文时的位置在
fork()
函数,创建时保存父进程的上下文和pc
值,所以不执行fork()
之前的代码。
Thinking4.3
C
fork
只在父进程中被调用了一次,在两个进程中各产生一个返回值
Thinking4.4
在空间0-USTACKTOP
中,非共享的页面或者只读的页面不用保护,其他需要duppage
保护起来。
具体有一些空间,UTOP
之上的空间用户进程不应操作,无需保护。UXSTACKTOP
用户进程异常栈,无需保护。USTACKTOP + BY2PG
显示Invalid memory
无需保护。
Thinking4.5
vpt
指向二级页表,即页表项。vpd
指向一级页表,即页目录。类似于数组或者指针的操作(*vpd) [va >> 22]
,(*vpt) [va >> 12]
。可以分别取页表项物理地址和va
对应的物理地址。
在entry.S
中
vpd:
.word (UVPT+(UVPT>>12)*4)
注意到计算vpd
即页目录地址,体现了自映射。
获取了地址一般可以修改,但是用户进程没有访问权限。
Thinking4.6
写时复制机制下,如果页面有COW
则需要进行中断重入。
用户态中需要处理中断,读取Trapfram
中的值,并且利用相关数据来恢复现场。
Thinking4.7
- 符合微内核的思想,用户空间可以临时执行内核的功能,当内核出现故障时操作系统不至于崩溃。
- 通用寄存器存入栈中,记录
sp
栈指针,读取数据时出栈,从而恢复后得到正确值。
Thinking4.8
syscall_env_alloc
函数执行过程中可能遇到异常,需要进行异常处理。- 此时中断处理还没有完全设置好,当触发缺页中断时,无法进行正确的处理。
- 子进程在执行时已经复制了父进程中
__pgfault_handler
的值,所以不需要赋值。
二、实验难点图示
中断,以及系统调用时如何通过特权指令syscall
陷入内核态,这一块理解地还不是很透彻。
系统调用的流程:
- 调用一个封装好的用户空间的库函数
- 调用用户空间的
syscall_
函数 - 调用
msyscall
,用于陷入内核态 - 陷入内核,内核取得信息,执行对应的内核空间的系统调用函数
- 执行系统调用,并返回用户态,同时将返回值“传递”回用户态
- 从库函数返回,回到用户程序调用处
内核态和用户态的栈空间的管理,进入handle_syscall
需要进行相关处理。出现页错误时,内核会把进程在一个新的栈(异常栈)上面重启,运行指定的用户级别页错误处理函数。
- 设置正确的
epc
值,从异常处理结束后继续返回到下一条指令。 - 取出系统调用号
- 在内核栈上正确存放参数
- 执行完毕后恢复内核栈指针位置
进程间通信ipc中需要的一些权限位的处理。
写时复制,copy on write
机制,先让父子进程共享相同的物理空间,设置异常处理栈和epc
值,要处理异常需要将epc
的值设置为page_fault_handler
,跳转至异常处理函数。
duppage
需要区分不同的权限,并且采取对应的处理。
- 只读页面 按照相同权限(只读)映射给子进程即可
- 共享页面 即具有
PTE_LIBRARY
标记的页面,这类页面需要保持共享的可写的状态 - 写时复制页面 即具有
PTE_COW
标记的页面,这类页面是上一次的fork
的duppage
的结果 - 可写页面 需要给父进程和子进程的页表项都加上
PTE_COW
标记
三、体会与感想
本lab实验总体上内容比较多,系统调用部分需要实现一些重要的函数。首先要理解好系统调用的流程,先从用户空间调用函数,之后由msyscall
陷入内核态,在内核态中我们实现了参数和信息的传递,内核态即可执行系统调用函数sys
,最终返回到用户空间,再从库函数中返回。
用户空间可以临时执行内核的功能,这是微内核的一种思想,设备驱动、文件系统可以放在用户空间实现,即使它们崩溃,也不会影响到整个系统的稳定。需要实现进程间的通信(ipc)
fork的copy on write
机制也有利于提高效率,并不直接复制。而是父子进程中有修改内存的行为发生时,内核捕获这种缺页中断后,再为发生内存修改的进程相应的地址分配物理页面。实现时还需要注意duppage
对于不同权限页需要有不同的处理方式。
代码的理解和debug依然存在问题,对于注释中前置条件和后置条件等,对于实现有一定的提示作用。但是自己有些地方还没有理解好,在实现时可能还是有一些细节没有考虑足够,所以在实现时依然存在了bug,花费大量时间才找到。总的来看,收获也很大。
标签:调用,用户,空间,内核,lab4,进程,实验报告,页面 From: https://www.cnblogs.com/ddl789/p/17215437.html