第1关:页目录和页表的变化
1.在 1 号进程第 1 次开始执行 output_char 函数调用时,线性地址空间到物理地址空间的映射关系是怎样的?
2.在 1 号进程第 2 次开始执行 output_char 函数调用时,线性地址空间到物理地址空间的映射关系是怎样的?
3.在 1 号进程的第 1、2 次 output_char 函数调用之间,页目录和页表发生了怎样的变化?
前面已经做过许多次在gdb模式下获取线性地址,这里不再描述,直接从bochsdbg模式开始。依旧是在0x69d9处打断点,并查看页目录地址
如果要查看分析线性地址空间到物理地址空间的映射关系,有两种方法,我采用的是比较简单的使用info tab命令,显示虚拟地址的映射情况(两次调用基本一致,仅以第一次为例)
还有一种较为复杂的方法可以采用,首先分析页目录中的每个有效的页目录项,找到所有二级页表的首地址;然后分析每一个二级页表,查看其中有效的页表项,计算出页面与页帧之间的对应关系。最后的映射关系类似描述如下:
至于页目录和页表发生了怎样的变化,就是存放mynext物理地址的页表项的值发生了数值变化。
最终答案:
在 1 号进程第 1 次开始执行 output_char 函数调用时,线性地址空间到物理地址空间的映射关系是怎样的?
1.(0x00000000-0x00ffffff->0x00000000-0x00ffffff)
2.(0x04000000-0x04024fff->0x00000000-0x00024fff)
3.(0x04025000-0x04025fff->0x00ffd000-0x00ffdfff)
4.(0x04026000-0x0409ffff->0x00026000-0x0009ffff)
在 1 号进程第 2 次开始执行 output_char 函数调用时,线性地址空间到物理地址空间的映射关系是怎样的?
5.(0x00000000-0x00ffffff->0x00000000-0x00ffffff)
6.(0x04000000-0x04021fff->0x00000000-0x00021fff)
7.(0x04022000-0x04022fff->0x00ffc000-0x00ffcfff)
8.(0x04023000-0x04024fff->0x00023000-0x00024fff)
9.(0x04025000-0x04025fff->0x00ffd000-0x00ffdfff)
10.(0x04026000-0x0409ffff->0x00026000-0x0009ffff)
在 1 号进程的第 1、2 次 output_char 函数调用之间,页目录和页表发生了怎样的变化?
11.页表项(0x00ffe088)的值由原来的(0x00022065)变为了(0x00ffc067)
第2关:用户栈和核心栈的物理位置
使用版本 1 内核时,在第 2 次进程调度后:
1. 0 号进程和 1 号进程的进程控制块的地址分别是多少?
2.执行到函数 task0 时,0 号进程的用户栈栈顶位于物理内存何处?
3.0 号进程执行到函数 sys_pause 时,核心栈栈顶位于物理内存何处?
4.执行到函数 task1 时,1 号进程的用户栈栈顶位于物理内存何处?
5.1 号进程执行到函数 sys_pause 时,核心栈栈顶位于物理内存何处?
在 bochsdbg 中,如何跟踪到第 2 次进程调度
首先查看函数 schedule 的地址,然后在该处设断点,并跟踪到此断点第 2 次出现。
在gdb模式下
得出0号进程和1号进程控制块的地址分别是0x1ea20、0xfff000我们在bochsdbg模式下就是根据这个判断进程号
在 bochsdbg 调试模式下,如何判断当前进程是几号进程
可以先在 gdb 调试模式下确定全局变量 current 的地址和 0 号进程的进程控制块的地址:
在上图中,0 号进程的进程控制块的地址是 0x1ea20 。
然后,在 bochsdbg 调试时,可以查看变量 current 的值,进而判断是不是在 0 号进程里
如何得到一个函数的地址
可以直接查看符号文件,如下所示:
可见函数 task0 的地址为 0x7963 。
我们先查看各个函数的地址信息
然后进入bochsdbg模式,在shedule(0x6d93)处打断点并连续c两次
然后把上面的断点关闭,在task0函数设断点(0x7963),并判断是否为进程0
如何知道当前栈顶的物理位置
当前栈顶的逻辑地址是 $ss:$esp ,只需要将这个地址转换为线性地址,并进而转换为物理地址即可。
那我们先用sreg命令和reg命令查看寄存器的值,求出逻辑地址
可以看到它的逻辑地址是0x2573c
之后求出其对应的物理地址
计算得出物理地址为0x2573c
剩下的几个问题和第一个问题类似,继续照着往下做即可,就不在此详解。
最终答案:
使用版本 1 内核时,在第 2 次进程调度后:
1.0 号进程和 1 号进程的进程控制块的地址分别是多少?(0x1ea20)(0xfff000)
2.执行到函数 task0 时,0 号进程的用户栈栈顶位于物理内存何处?(0x2573c)
3.0 号进程执行到函数 sys_pause 时,核心栈栈顶位于物理内存何处?(0x1f9f0)
4.执行到函数 task1 时,1 号进程的用户栈栈顶位于物理内存何处?(0xffd73c)
5.1 号进程执行到函数 sys_pause 时,核心栈栈顶位于物理内存何处?(0xffffd0)