date: 2019-02-19
tags: OS 6.828
第一个任务是让每次调用system call的时候,都会输出其名字和返回值。需要修改的代码是syscall.c
我就直接用了暴力方法,如下:
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]();
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;
}
}
至于如何输出system call arguments,应该是要用curproc->tf
里面的值吧,具体具体没想好。
这样之后,直接运行kernel的结果是:
...
fork -> 2
exec -> 0
open -> 3
close -> 0
$write -> 1
write -> 1
注意在做这一问的时候,最好把part 1的print给注释掉,不然太乱了。
如题目所说,仿照uptime
,有:
$ grep -n uptime *.[chS]
syscall.c:105:extern int sys_uptime(void);
syscall.c:122:[SYS_uptime] sys_uptime,
syscall.c:147:[SYS_uptime] "uptime",
syscall.h:15:#define SYS_uptime 14
sysproc.c:83:sys_uptime(void)
user.h:25:int uptime(void);
usys.S:31:SYSCALL(uptime)
所以在syscall.h
中加入SYS_date
,extern int sys_date(struct rtcdate*);
。之后,在sysproc.c
中加入:
int sys_date(void)
{
struct rtcdate *r;
if(argptr(0, &p, sizeof(struct rtcdate)) < 0)
return -1;
return cmostime(r);
}
在user.h
中加入int sys_date(struct rtcdate*);
。在usys.S
中加入SYSCALL(date)
。
之后按照要求加入加入date.c
文件,进行修改:
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, "UTC %d-%d-%d %d:%d:%d\n", r.year, r.month, r.day, \
r.hour, r.minute, r.second);
exit();
}
最后,在Makefile
的UPPROGS
中加入_date
。就大功告成了。
$ date
UTC 2019-2-19 19:6:33
注意,xv6的printf
没有实现%02d
这样的操作,所以也没办法了。
这个作业的目的就是为了总结一下,大致应该是在sh
中调用date
会调用date.c
,而date.c
中调用的date
函数被定义在了user.h
头文件中,user.h
的函数中的system call都是由usys.S
实现的,实现的方式就是调用了一个叫SYSCALL(name)
的宏,其操作为:
#define SYSCALL(name) \
.globl name; \
name: \
movl $SYS_ ## name, %eax; \
int $T_SYSCALL; \
ret
也就是会调用INT
指令的。make
了之后,我们可以看到,sh.asm
果然出现了
00000db2 <date>:
db2: b8 16 00 00 00 mov $0x16,%eax
db7: cd 40 int $0x40
db9: c3 ret
dba: 66 90 xchg %ax,%ax
dbc: 66 90 xchg %ax,%ax
dbe: 66 90 xchg %ax,%ax
使用INT
指令开始,就和note4中记录的调用write
一样了。在Makefile
中加入date.c
应该只是为了编译出date的二进制文件用的吧,这个我还不清楚...