Lab2

mit 6.s081 lab2

Lab2怎么说呢,总觉得挺奇怪的,第一次接触系统调用代码,有点小懵,一个trace就做了我1个多小时。

lab1的时候只添加函数还是挺友好的,就跟平常写代码一样,这个系统调用就绕来绕去的,贼麻烦,也算体验到工程代码的<<乐趣>>?

不过还是得称赞一下lab2得Hints,没有它感觉根本做不下去:::

System call tracing(moderate)

首先看一下Hints,先pass掉那些test用例,后面再看:

lab2提示and我的提示:

  • MakefileUPROGS中添加$U/_trace

    • 这一步比较简单,就像lab1那样在makefile里面添加即可

  • 运行make qemu,您将看到编译器无法编译user/trace.c,因为系统调用的用户空间存根还不存在:将系统调用的原型添加到user/user.h,存根添加到user/usys.pl,以及将系统调用编号添加到kernel/syscall.hMakefile调用perl脚本user/usys.pl,它生成实际的系统调用存根user/usys.S,这个文件中的汇编代码使用RISC-V的ecall指令转换到内核。一旦修复了编译问题(注:如果编译还未通过,尝试先*make clean*,再执行*make qemu*),就运行trace 32 grep hello README;但由于您还没有在内核中实现系统调用,执行将失败。

    • 这里就纯粹按照提示去干

    • 首先到user/user.h添加一个 int trace(int); (仿照上面那些,看着就知道要干嘛了

    • 然后到user/usys.pl添加存根 entry("trace");

    • 最后到kernel/syscall.h添加 #define SYS_trace 22

    • 编译完可以看到user/usys.S里面新增了

      trace: 
      li a7, SYS_trace 
      ecall  
      ret
  • kernel/sysproc.c中添加一个sys_trace()函数,它通过将参数保存到proc结构体(请参见kernel/proc.h)里的一个新变量中来实现新的系统调用。从用户空间检索系统调用参数的函数在kernel/syscall.c中,您可以在kernel/sysproc.c中看到它们的使用示例。

  • 修改fork()(请参阅kernel/proc.c)将跟踪掩码从父进程复制到子进程。

  • 修改kernel/syscall.c中的syscall()函数以打印跟踪输出。您将需要添加一个系统调用名称数组以建立索引。

跟着上面到第二步就可以 make qemu 进去看看了,然后输一下测试用例试试,就会出现 trace fail

接下来就是 三四五 这三步来真正写代码

第三步主要是实现sys_trace 函数:

首先需要按照提示的:它通过将参数保存到proc结构体(请参见kernel/proc.h)里的一个新变量中来实现新的系统调用。可以知道,需要在 proc.h里面的结构体添加个新变量:

然后按照提示就可以继续在 kernel/sysproc.c 里面添加一个 sys_trace 函数:

这个函数的实现就是说如果系统调用 sys_trace called,就将 traceMask 赋值为 命令行带进来的参数,如:

然后到第四步,在kernel/proc.c的 fork() 加一行语句将 跟踪掩码从父进程复制到子进程:

第五步:修改kernel/syscall.c中的syscall()函数以打印跟踪输出,按照提示需要先建立一个名称索引。(wc,第一次见到这种写法,属实牛皮

最后就是要修改 syscall()函数来输出了

finally : 有个通过的小细节啊,上面的printf中间全要用空格,我刚开始用 tab,test还给我报了三个错....

最后我自己总结一下调用的,因为写完这文章再回顾还是得继续看 Hints:

Makefile调用perl脚本user/usys.pl,它生成实际的系统调用存根user/usys.S ->

sh 调用 trace 指令 ->

trace.c 将 argv[1] 传入 user/user.h 的 int trace(int) ->

user/user.h的存根在user/usys.pl 的entry("trace"); 进入系统调用 ->

syscall()在if语句里面进入kernel/sysproc.c中,执行 sys_trace(),将argv[1]添加到myproc()->traceMask中 ->

进程状态就被trace标记上了,然后转回trace.c,执行exec ->

在exec源码中这个struct proc *p = myproc();是带有traceMask的 ->

然后一执行syscall就会被判断到,然后输出我们想要跟踪的状态,如果是fork了的话,也会通过我们在fork里面给子进程添加的traceMask进而跟踪子进程

可能总结的不对,之后学明白了再回来看看需不需要改

Sysinfo(moderate)

在Makefile add $U/_sysinfotest\

在user.h add

在usys.pl add entry("sysinfo");

在kernel/syscall.h添加 #define SYS_sysinfo 23

在sysproc.c添加:

在defs.h的不同位置添加上面两个函数,根据文件的注释就行

在kalloc.c添加:

我最开始是直接count++,发现test的时候错了,报的那个正确数是我得到的 4096倍,因此发现了PGSIZE的含义: #define PGSIZE 4096 // bytes per page

在proc.c添加:

其他一些需要的添加跟上面一样,如果要使用trace debug的话参照我上面的添加就行,感觉trace还是写的很鸡肋,在我debug的过程中没有产生任何作用,还得是老师的测试脚本

Last updated