Part One: System call tracing 任務:修改Xv6內核的代碼來列印出每個系統調用以及返回值 根據提示,應該在syscall.c中修改syscall()。 首先在syscall.c中增加對應系統調用名稱的數組: static char *syscalls_name[] = { ...
Part One: System call tracing
任務:修改Xv6內核的代碼來列印出每個系統調用以及返回值
根據提示,應該在syscall.c中修改syscall()。
首先在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",
};
接著在syscall()中添加列印命令:
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;
}
}
最終執行結果如下:
xv6...
cpu0: starting 0
sb: size 1000 nblocks 941 ninodes 200 nlog 30 logstart 2 inodestart 32 bmap start 58
exec -> 0
open -> 0
dup -> 1
dup -> 2
iwrite -> 1
nwrite -> 1
iwrite -> 1
twrite -> 1
:write -> 1
write -> 1
swrite -> 1
twrite -> 1
awrite -> 1
rwrite -> 1
twrite -> 1
iwrite -> 1
nwrite -> 1
gwrite -> 1
write -> 1
swrite -> 1
hwrite -> 1
write -> 1
fork -> 2
exec -> 0
open -> 3
close -> 0
$write -> 1
write -> 1
註:shell的輸出和系統調用的調用路徑混在了一起,原因是shell是通過系統調用write來列印輸出的
Part Two: Date System Call
任務: 在Xv6中新增一個系統調用date。使用定義於lapic.c中的函數cmostime(),以系統調用uptime為例,觀察如何添加一個系統調用。並且在用戶層添加一個調用系統調用date的程式。
- 首先使用grep - n uptime *.[chS]命令在源碼中查找uptime相關的代碼,接下來逐個查看搜索到的位置,模仿寫出date系統調用所需要的代碼
❯ grep -n uptime *.[chS]
syscall.c:105:extern int sys_uptime(void);
syscall.c:121:[SYS_uptime] sys_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.c的對應位置添加代碼後如下:
extern int sys_chdir(void);
extern int sys_close(void);
extern int sys_dup(void);
extern int sys_exec(void);
extern int sys_exit(void);
extern int sys_fork(void);
extern int sys_fstat(void);
extern int sys_getpid(void);
extern int sys_kill(void);
extern int sys_link(void);
extern int sys_mkdir(void);
extern int sys_mknod(void);
extern int sys_open(void);
extern int sys_pipe(void);
extern int sys_read(void);
extern int sys_sbrk(void);
extern int sys_sleep(void);
extern int sys_unlink(void);
extern int sys_wait(void);
extern int sys_write(void);
extern int sys_uptime(void);
extern int sys_date(void); // 新添加
static int (*syscalls[])(void) = {
[SYS_fork] sys_fork,
[SYS_exit] sys_exit,
[SYS_wait] sys_wait,
[SYS_pipe] sys_pipe,
[SYS_read] sys_read,
[SYS_kill] sys_kill,
[SYS_exec] sys_exec,
[SYS_fstat] sys_fstat,
[SYS_chdir] sys_chdir,
[SYS_dup] sys_dup,
[SYS_getpid] sys_getpid,
[SYS_sbrk] sys_sbrk,
[SYS_sleep] sys_sleep,
[SYS_uptime] sys_uptime,
[SYS_open] sys_open,
[SYS_write] sys_write,
[SYS_mknod] sys_mknod,
[SYS_unlink] sys_unlink,
[SYS_link] sys_link,
[SYS_mkdir] sys_mkdir,
[SYS_close] sys_close,
[SYS_date] sys_date, // 新添加
};
- 在syscall.h中添加代碼:
#define SYS_date 22
- 在user.h中添加代碼:
int date(struct rtcdate*);
- 在usys.S中添加代碼:
SYSCALL(date)
- 在sysproc.c中添加代碼:
int sys_date(void) {
struct rtcdate* r = 0;
if (argptr(0, (char**)&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;
if (date(&r)) {
printf(2, "date failed\n");
exit();
}
printf(1, "%d-%d-%d %d:%d:%d\n", r.year, r.month, r.day, r.hour, r.minute, r.second);
exit();
}
- 在Makefile中的UPROG中添加
_date\
在完成以上步驟後,成功添加了系統調用date以及調用它的命令date,測試結果如下:
xv6...
cpu0: starting 0
sb: size 1000 nblocks 941 ninodes 200 nlog 30 logstart 2 inodestart 32 bmap start 58
init: starting sh
$ date
2022-11-10 18:19:21
$