计算机系统综合实践报告
实验进度
任务 | 完成 |
---|---|
必做任务1 | 完成 |
必做任务2 | 完成 |
必做任务3 | 完成 |
必做任务4 | 完成 |
选做任务1 | 完成 |
选做任务2 | 完成 |
选做任务3 | 完成 |
思考题
思考题1
段选择符index是$2^13$,最多可以$2^13$个段描述符
思考题2
不可以,因为虚拟地址就是需要通过GDT进行转换,如果GDT的首地址都是虚拟地址那么就没有东西可以转换GDT的虚拟地址了
思考题3
在段寄存器中保存基地址和限制
思考题4
段的体积大,在内存中无法做到连续存储,容易形成外碎片,降低内存利用率。
思考题5
分页式管理便于进行内存调度,并且没有外碎片,内碎片不超过页的大小
思考题6
因为低12位是页内偏移,可以直接根据虚拟地址给出,不需要进行转换
不能,GDT使用线性地址一样,CR3是用于物理地址转换的,如果他也是虚拟地址就没有什么可以转换CR3的线性地址了。
一级页表有占用内存过多的缺点。而二级页表虽然看上去消耗内存反而增大了,但是实际上很多对应ptable并没有实际创建因而减小了内存。
思考题7
空指针并不是空的,只是指向的地址是0,属于操作系统无法访问。
思考题8
在页表项中有权限位,进行地址转换时首先检查权限位
思考题9
思考题10
原本的最后ptable会到负数,ptable[-1]
思考题11
问题1
因为这里定义的x生成的地址是虚拟地址,超过了物理地址的界限,报错说0xc014a000 outside of the physical memory.
而kvm.c中的虚拟地址都经过了va_to_pa的转换,在物理地址范围之内
问题2
两个虚拟地址指向同一个物理地址是因为在0xc0100000
上的在init_mm中作为今后访问内核的虚拟地址,另一份在updir没有正常使用时让虚拟地址得以正常翻译
问题3
出现了present = 0的错误。因为开启paging位之后,所有地址都需要进行虚拟地址转换,而esp还是使用开始的物理地址发现这个虚拟地址下并没有使用。
问题4
出现的问题和上面相同,使用init_cond()会先push 再jmp,之后又会通过ret进行返回。通过调试得到是在loader中出现问题的,而在lnaddr_read和lnaddr_write处监视发现对应栈的位置也只读写了一次。只能推测是因为将地址压入栈导致栈溢出
实验遇到的问题
因为这个实验跨度比较长,结果出现了cache没有写完就去写后面的分段分页的情况。结果写分页的时候始终出现了问题,于是便一条条代码去查看。在kvm.c的内联汇编处发现了stos只有第一次会正确写入,之后变不会写到内存,但是如果使用swaddr_read()读取了一下内存(当时用x命令查看)就能正常写入。当时花了近一天的时间才想到可能是内存相关函数的原因,然后就在内存函数中逐条追踪返回值,才发现原来cache没有写完。
在写段结构的lgdt命令时发现将数直接转换成指针可能会出现一些奇奇怪怪的问题。然后就直接访问内存读取数据然后进行拼接。但是之后发现是可以(PDE)(void)之类的方式进行转换的。甚至可以使用绝对地址进行函数跳转 (void(*)(void)eip)()。是一个参数为void 返回值为void 地址为eip的函数。
实验心得
- 对分段、分页、cache的实现有了更深的理解
- 对地址和指针之间的转换更加熟练