MIT6.s081-lab-syscall
Using gdb
如果不知道怎么运行gdb的,要先看提供的文档
1.首先在终端1中运行make qemu-gdb
,结尾处会得到一个端口号,供终端2使用
2.新起一个终端,运行riscv64-unknown-elf-gdb
,会进入如下所示的界面
3.输入target remote localhost: 25501
,然后再输入file kernel/kernel
,就可以跟着指示往下做了
问题1:Looking at the backtrace output, which function called
syscall
?usertrap()
问题2:What is the value of
p->trapframe->a7
and what does that value represent?
从initcode.S
文件中看到a7
保存的是要执行的系统调用号,从syscall.h
中看到7
是SYS_exec
7和exec的系统调用号
问题3:What was the previous mode that the CPU was in?
通过输入p /x $sstatus
,得到0x200000022
,通过查询相关文档得到之前的特权级别是user mode
,其中的8
这个位置SPP
就表示源自什么模式(0表示用户模式)。
用户模式
问题4:Write down the assembly instruction the kernel is panicing at. Which register corresponds to the variable
num
?
跟着作业的指示走,在kernel.asm
文件中搜索地址可以看到:
在lw a3,0(zero)处panic,存在寄存器a3中
问题5:Why does the kernel crash? Hint: look at figure 3-3 in the text; is address 0 mapped in the kernel address space? Is that confirmed by the value in
scause
above?内核因为加载了一个未使用的地址 0 处的内存数据而崩溃(Load page fault)。地址 0 并不映射到内核空间中(从
0x80000000
开始)。问题6:What is the name of the binary that was running when the kernel paniced? What is its process id (
pid
)?这个二进制的名字为
initcode
,其 process id 为 1.
System call tracing
建议先读几遍作业文档,这两个作业需要实现的逻辑不难,但是这个流程稍微多了些
- 首先在
Makefile
中添加$U/_trace\
- 然后在
user.h
文件中注册对应的函数
- 在
usys.pl
文件中也添加对应的入口
- 在
syscall.h
文件中添加对应的系统调用号
- 在
sysproc.c
文件中实现sys_trace
函数,从用户态获取到用户输入的mask
,然后赋值给进程的syscall_trace
成员,该成员需要在proc.h
文件中的proc
结构体添加
- 在
proc.c
文件中修改fork
函数,在父进程创建子进程的时候将该值复制过去,如下
- 最后修改
syscall.c
文件中的syscall
函数,在进行系统调用的时候根据mask
打印相应的信息
Sysinfo
该实验流程跟前面的差不多,这里主要描述一下freemem
和nproc
怎么计算得到的,根据课程的作业提示我们在kalloc.c
文件中创建一个count_freeMem
用来返回空闲的内存字节数,至于为什么是这么计算,因为可以看出来xv6
系统使用的是空闲链表法来分配内存的
1 | // 返回空闲内存的字节数=空闲页数*每页字节数 |
并且在proc.c
文件中创建一个count_process
用来返回不是UNUSED
状态的进程数量
1 | // 返回已经分配的进程数 |
这两个函数也都很直观,应该是没什么难度,最后跑一下make grade
看看得分吧~