Homework: xv6 system calls
Part One: System call tracing
第一个作业的要求是在运行xv6的时候,窗口可以自动打印出系统调用的名字和返回值。即系统自动输出如下部分:
由于系统调用函数syscall()在syscall.c文件中,所以我们只需要修改syscall.c文件即可,对于这道题,只需要在syscall函数中添加对应的printf语句就行。
- 首先我们要查看syscall.h文件,这里面定义了系统调用的名称和对应的序号,我们要在终端上显示的就是这里面对应的名字和编号。
syscall.h文件代码如下:
// System call numbers
#define SYS_fork 1
#define SYS_exit 2
#define SYS_wait 3
#define SYS_pipe 4
#define SYS_read 5
#define SYS_kill 6
#define SYS_exec 7
#define SYS_fstat 8
#define SYS_chdir 9
#define SYS_dup 10
#define SYS_getpid 11
#define SYS_sbrk 12
#define SYS_sleep 13
#define SYS_uptime 14
#define SYS_open 15
#define SYS_write 16
#define SYS_mknod 17
#define SYS_unlink 18
#define SYS_link 19
#define SYS_mkdir 20
#define SYS_close 21
- 进入syscall.c文件进行修改。
首先在文件的开始添加编号和系统调用名称相互对应的数组,代码如下:
#include "types.h"
#include "defs.h"
#include "param.h"
#include "memlayout.h"
#include "mmu.h"
#include "proc.h"
#include "x86.h"
#include "syscall.h"
//以下为添加数组
static char SYS_call_names[][6] = {
[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"};
然后修改对应syscall函数,只需在if中添加一条cprintf语句即可,如下:
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]();
//这条语句
cprintf("%s -> %d\n", SYS_call_names[num], num);
//....
} else {
cprintf("%d %s: unknown sys call %d\n",
curproc->pid, curproc->name, num);
curproc->tf->eax = -1;
}
- 然后在terminal中用make qemu运行即可产生如下结果:
Part Two: Date system call
第二个任务是要自己添加一个新的系统调用,并且能够返回当前系统时间。
- 首先在syscall.h中添加系统调用的编号。
#define SYS_date 22
- 然后在syscall.c中添加系统调用函数的声明。
需要在三个地方分别加上三个声明。如下代码:
//static char SYS_call_names[][6]中的
[SYS_date] "date"
extern int sys_date(void)
//static int (*syscalls[])(void)中的
[SYS_date] sys_date,
- 在user.h 中添加date函数的定义。
int date(struct rtcdate*);
- 在usys.S中最后一行加上如下函数。
SYSCALL(date)
- 在sysproc.c中添加系统调用函数的实现。
int
sys_date(struct rtcdate *r)
{
if (argptr(0,(void *)&r, sizeof(*r)) <0)
return -1;
cmostime(r);
return 0;
}
- 新建一个date.c文件,加入到xv6源码文件夹中。
date.c 为:
#include "types.h"
#include "user.h"
#include "date.h"
int
main(int argc, char *argv[])
{
struct rtcdate r;
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.year, r.month, r.day, r.hour, r.minute, r.second);
exit();
}
7.在Makefile文件中添加UPROGS对应命令的定义。
_zombie\
_big\
//这个为添加内容
_date\
//。。。
- 为了防止上一个任务中的输出结果影响这个结果,我们需要先将syscall.c中的部分代码注释掉。
//Static Char Sys_Call_Names[][6] = {
// [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",
// [Sys_Date] "Date"};
//和syscall中的这行
//cprintf("%s -> %d\n", SYS_call_names[num], num);
- 最后在terminal中输入make qemu编译运行,输入date命令,即可出现如下结果: