HW3 system calls

Homework: xv6 system calls

参考boot homework中的内容,为xv6操作系统添加一个系统调用。

链接:https://pdos.csail.mit.edu/6.828/2018/homework/xv6-syscall.html

Part One: System call tracing

修改xv6内核,为每个系统调用打印一行,打印系统调用的名称和返回值。

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
static char syscall_name[][10] = {
[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"
};

首先类似于指针函数那样,准备一个名称数组,便于快速打印;

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
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", syscall_name[num], curproc->tf->eax);
} else {
cprintf("%d %s: unknown sys call %d\n",
curproc->pid, curproc->name, num);
curproc->tf->eax = -1;
}
}

然后添加打印具体的系统调用名称即可,根据x86的函数调用堆栈关系,返回值保存在eax寄存器之中,因此需要将进程页帧中的eax寄存器的值进行打印。

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
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", syscall_name[num], curproc->tf->eax);
int *fd;
switch(num){
case SYS_fork:
cprintf("sys_fork no args\n");
break;
case SYS_exit:
cprintf("sys_exit no args\n");
break;
case SYS_wait:
cprintf("sys_wait no args\n");
break;
case SYS_pipe:
if(argptr(0, (void*)&fd, 2*sizeof(fd[0]))<0){
cprintf("error: sys_pipe cannot get the args\n");
}
cprintf("sys_pipe args: %p %p",&fd[0],&fd[1]);
break;
default:
break;
}
} else {
cprintf("%d %s: unknown sys call %d\n",
curproc->pid, curproc->name, num);
curproc->tf->eax = -1;
}
}

同样打印系统调用时的参数,仍然根据x86的堆栈关系,进行打印,具体的用法,在syscall.c的前边儿给出了几个辅助函数,进程的context内保存了%esp,通过从堆栈内部查找指定字节长度的值,来进行获取参数,同时参考具体的系统调用的程序来进行参数的获取于打印。

Part Two: Date system call

写一个用户态的应用,进行系统调用,给出具体的UTC时间。

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
#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();
}

printf(1, "UTC date: %d-%d-%d %d:%d:%d\n", r.year, r.month, r.day, r.hour, r.minute, r.second);
exit();
}

首先添加一个用户程序,进行系统调用,并且将具体的日期输出到标准输出端口。同时在Makefile里边儿添加用户调用的编译选项。

uptime 系统调用组成

参照uptime的系统调用组成部分,对每个文件内的内容进行添加,分别是:

  • 在user.h中添加
1
int date(struct rtcdate*);
  • 在usys.S中添加
1
SYSCALL(date)
  • 在syscall.h中添加
1
#define SYS_date   22
  • 在文件syscall.c中添加
1
2
3
extern int sys_date(void);
// syscalls array add
[SYS_date] sys_date,
  • 在文件sysproc.c中添加
1
2
3
4
5
6
7
8
int sys_date(void) {
struct rtcdate*;
if (argptr(0, (char**)&r, sizeof(*r)) < 0) {
return -1;
}
cmostime(r);
return 0;
}

按照上述运行结果:

运行结果


HW3 system calls
https://www.bencorn.com/2022/07/01/HW3-system-calls/
作者
Bencorn
发布于
2022年7月1日
许可协议