Part One: System call tracing
实验内容
任务是修改xv6内核,使得每一次系统调用打印出一行代码,格式为:
系统调用名称->系统调用返回值
样例:
fork -> 2
exec -> 0
open -> 3
close -> 0
$write -> 1
write -> 1
实验过程
在github上下载xv6-public的代码并进入该目录下。vim syscall.c
根据注释可知系统调用number在%eax里,也就是说syscalls[]()函数返回的是系统调用number,并且把它存储在值 curproc->tf->eax内。所以只需要把系统调用名称输出即可。代码如下:
/*定义系统调用名称*/
static char *syscalls_name[] = {
[SYS_fork] "fork",
[SYS_exit] "exit",
[SYS_wait] "wait",
[SYS_pipe] "pipe",
[SYS_read] "read",
[SYS_kill] "kill",
[SYS_exec] "exec",
[SYS_fstat] "fstat",
[SYS_chdir] "chdir",
[SYS_dup] "dup",
[SYS_getpid] "getpid",
[SYS_sbrk] "sbrk",
[SYS_sleep] "sleep",
[SYS_uptime] "uptime",
[SYS_open] "open",
[SYS_write] "write",
[SYS_mknod] "mknod",
[SYS_unlink] "unlink",
[SYS_link] "link",
[SYS_mkdir] "mkdir",
[SYS_close] "close",
};
void
syscall(void)
{
int num;
struct proc *curproc = myproc();
num = curproc->tf->eax;
if(num > 0 && num < NELEM(syscalls) && syscalls[num]) {
curproc->tf->eax = syscalls[num]();
/*按照格式输出名称和number*/
cprintf("%s -> %d\n",syscalls_name[num],curproc->tf->eax);
} else {
cprintf("%d %s: unknown sys call %d\n",
curproc->pid, curproc->name, num);
curproc->tf->eax = -1;
}
}
实验结果
make qemu后出现结果
Part Two: Date system call
实验内容
添加一个date系统调用,按照自己规定的格式返回时间。
实验过程
使用grep -n uptime *.[chS] 追踪uptime系统调用。
date系统调用仿写uptime,在追踪到的头文件和c文件中补充代码。
值得注意的是,在user.h中是函数的定义,按照官方给出的需要补充在date.c的代码,我们在user.h中添加函数定义:
int date(struct rtcdate*); 其他均按照uptime的格式即可。
在sysproc.c中sys_date(void)代码:
int sys_date(void){
struct rtcdate *r;
if(argptr(0,(void *)&r, sizeof(*r)) < 0)
return -1;
cmostime(r);
return 0;
}
date.c的代码:
#include "types.h"
#include "user.h"
#include "date.h"
int
main(int argc, char *argv[])
{
struct rtcdate r;
// printf("running date");
if (date(&r)) {
printf(2, "date failed\n");
exit();
}
// your code to print the time in any format you like...
printf(1, "%d-%d %d %d:%d:%d\n", r.month, r.day, r.year, r.hour, r.minute, r.second);
exit();
}
实验结果
make qemu后在qemu仿真器里输入命令,出现结果
小结
对于date命令的执行,推测过程应该是这样:命令行输入date,找到date.c文件开始执行,执行到date(&r)语句时,因为在usys.S文件中声明了SYSCALL(date),所以发现这是个系统调用,于是开始陷入。发现sys_date系统调用执行函数,将参数r赋值,系统调用执行结束,返回用户进程,恢复到date.c/main函数执行现场,继续执行输出时间。
ATTENCION
在进行任务二的时候,需要把任务一中更改的代码注释,恢复到原状。不然在qemu中无法进行命令的输入。可能是因为shell的输出和系统调用跟踪是混合的,因为shell使用write syscall来打印它的输出。 (这是官网给出的提示,难道就是提示这个的?)
另外两个challenge都没有做,先放一放...涉及到寄存器就搞不懂惹...