第1关:进程创建前后页目录和页表的变化
本关任务:
1.在 0 号进程执行 fork 系统调用之前,线性地址空间到物理地址空间的映射关系是怎样的? 2.在 0 号进程刚执行完 fork 系统调用时,线性地址空间到物理地址空间的映射关系是怎样的?
3.在 0 号进程执行 fork 系统调用前后,页目录发生了怎样的变化?
一般而言,可以在该系统调用处设置断点,跟踪到该断点,然后使用 si 命令单步执行到陷入指令。但是,对于 main 函数里的 fork 系统调用,不能这样操作(因为 gdb 有时断点设置不够准),可以先跟踪到前一行的 move_to_user_mode 语句,然后使用 n 单步执行,即可到达 fork 系统调用的开始,此时再反汇编,找到陷入指令:
可以看到陷入指令的地址是0x6908,等会在bochsdbg模式将断点打在这个地址
查看0号进程控制块的地址和对应值,以便于在bochsdbg模式下判断进程号
在dbg模式下将断点打到陷入指令地址,并查看当前进程是否为0号进程
查看线性地址空间和物理地址空间映射关系
观察页目录内容
使用next命令执行fork系统调用,并再次查看线性地址空间和物理地址空间映射关系
分析页目录变化
最终答案:
在 0 号进程执行 fork 系统调用之前,线性地址空间到物理地址空间的映射关系是怎样的?
1.(0x00000000-0x00ffffff->0x00000000-0x00ffffff)
在 0 号进程刚执行完 fork 系统调用时,线性地址空间到物理地址空间的映射关系是怎样的?
2.(0x00000000-0x00ffffff->0x00000000-0x00ffffff)(0x04000000-0x0409ffff->0x00000000-0x0009ffff)
在 0 号进程执行 fork 系统调用前后,页目录发生了怎样的变化?
3.页目录项(0xc)的值由原来的(0x4007)变为了(0x4027)
4.页目录项(0x40)的值由原来的(0x0)变为了(0xffe007)
第2关:1 号进程对 mynext 变量的第一次修改
本关任务:
1.1 号进程修改 mynext 变量的指令地址是多少?
2.1 号进程的 mynext 变量的线性地址是多少?
3.在 1 号进程第一次修改 mynext 变量之前,上述线性地址对应的页表项的值是多少?该线性地址被映射到的物理地址(旧物理地址)是多少?
4.在 1 号进程第一次修改 mynext 变量时,会引发页故障,在页故障处理程序刚开始执行时,CR2 寄存器的值是多少?
5.在此页故障处理完回到恢复点时,恢复点的地址是什么?此时上述线性地址对应的页表项的值是多少?该线性地址被映射到的物理地址(新物理地址)是多少?
6.在恢复点指令执行后,上述新物理地址处的值是多少?上述旧物理地址处的值是多少?
首先去到源码,1号进程修改mynext变量的代码在156行,所以在gdb模式下在156行打断点,进行反汇编
值得注意的是,这里修改 mynext 变量的指令地址要精确到汇编指令,所以地址是0x6988而不是0x6980
查看mynext的偏移地址
去bochsdbg模式,进行到断点位置
sreg命令查看ds寄存器的值
查看mynext变量的线性地址
查看对应页表项的值和物理地址
页表项的值是0x22065,物理地址是0x2282c
s命令进入页故障处理程序
creg命令查看CR2寄存器的值
通过u命令进行反汇编,找到iret指令,并通过设置断点回到恢复点
这里应该将断点打到0xb1d6,我打到了0xb1d5,所以多执行了一次s
可以看到恢复点地址是0x6988
查看对应页表项的值和物理地址
s命令执行该恢复点,然后查看新、旧物理地址处的值
最终答案:
1.1 号进程修改 mynext 变量的指令地址是多少?(0x6988)
2.1 号进程的 mynext 变量的线性地址是多少?(0x402282c)
3.在 1 号进程第一次修改 mynext 变量之前,上述线性地址对应的页表项的值是多少?(0x22065)该线性地址被映射到的物理地址(旧物理地址)是多少?(0x2282c)
4.在 1 号进程第一次修改 mynext 变量时,会引发页故障,在页故障处理程序刚开始执行时,CR2 寄存器的值是多少?(0x402282c)
5.在此页故障处理完回到恢复点时,恢复点的地址是什么?(0x6988)此时上述线性地址对应的页表项的值是多少?(0xffc007)该线性地址被映射到的物理地址(新物理地址)是多少?(0xffc82c)
6.在恢复点指令执行后,上述新物理地址处的值是多少?(0x2)上述旧物理地址处的值是多少?(0x1)