System call tracing (moderate)
在Makefile的UPROGS中添加$U/_trace
diff --git a/Makefile b/Makefile
index f0beb51..f07531b 100644
--- a/Makefile
+++ b/Makefile
@@ -149,7 +149,7 @@ UPROGS=\
$U/_grind\
$U/_wc\
$U/_zombie\
$U/_trace\
ifeq ($(LAB),trap)
系统调用的用户空间存根还不存在:
将系统调用的原型添加到user/user.h
diff --git a/user/user.h b/user/user.h
--- a/user/user.h
+++ b/user/user.h
@@ -23,6 +23,7 @@ int getpid(void);
char* sbrk(int);
int sleep(int);
int uptime(void);
int trace(int);
// ulib.c
int stat(const char*, struct stat*);
存根添加到user/usys.pl
diff --git a/user/usys.pl b/user/usys.pl
--- a/user/usys.pl
+++ b/user/usys.pl
@@ -36,3 +36,4 @@ entry("getpid");
entry("sbrk");
entry("sleep");
entry("uptime");
entry("trace");
\ No newline at end of file
将系统调用编号添加到kernel/syscall.h
diff --git a/kernel/syscall.h b/kernel/syscall.h
--- a/kernel/syscall.h
+++ b/kernel/syscall.h
@@ -20,3 +20,4 @@
#define SYS_link 19
#define SYS_mkdir 20
#define SYS_close 21
#define SYS_trace 22
\ No newline at end of file
此时尝试执行trace 32 grep hello README
bash
$ trace 32 grep hello README
3 trace: unknown sys call 22
trace: trace failed
在kernel/sysproc.c中添加一个sys_trace()函数uint64
diff --git a/kernel/sysproc.c b/kernel/sysproc.c
--- a/kernel/sysproc.c
+++ b/kernel/sysproc.c
@@ -95,3 +95,16 @@ sys_uptime(void)
release(&tickslock);
return xticks;
}
uint64
sys_trace(void)
{
// 获取掩码参数
int mask;
if(argint(0, &mask) < 0)
return -1;
struct proc *p = myproc();
p->trace_mask=mask;
return 0;
}
将参数保存到proc结构体(请参见kernel/proc.h)里的一个新变量中来实现新的系统调用
diff --git a/kernel/proc.h b/kernel/proc.h
--- a/kernel/proc.h
+++ b/kernel/proc.h
@@ -93,6 +93,7 @@ struct proc {
int killed; // If non-zero, have been killed
int xstate; // Exit status to be returned to parent's wait
int pid; // Process ID
int trace_mask;
// these are private to the process, so p->lock need not be held.
uint64 kstack; // Virtual address of kernel stack
修改fork()(请参阅kernel/proc.c)将跟踪掩码从父进程复制到子进程
diff --git a/kernel/proc.c b/kernel/proc.c
--- a/kernel/proc.c
+++ b/kernel/proc.c
@@ -291,6 +291,9 @@ fork(void)
safestrcpy(np->name, p->name, sizeof(p->name));
//将trace_mask拷贝到子进程
np->trace_mask = p->trace_mask;
pid = np->pid;
np->state = RUNNABLE;
修改kernel/syscall.c中的syscall()函数以打印跟踪输出。您将需要添加一个系统调用名称数组以建立索引
diff --git a/kernel/syscall.c b/kernel/syscall.c
--- a/kernel/syscall.c
+++ b/kernel/syscall.c
@@ -104,6 +104,7 @@ extern uint64 sys_unlink(void);
extern uint64 sys_wait(void);
extern uint64 sys_write(void);
extern uint64 sys_uptime(void);
extern uint64 sys_trace(void);
static uint64 (*syscalls[])(void) = {
[SYS_fork] sys_fork,
@@ -127,6 +128,12 @@ static uint64 (*syscalls[])(void) = {
[SYS_link] sys_link,
[SYS_mkdir] sys_mkdir,
[SYS_close] sys_close,
[SYS_trace] sys_trace,
};
static char *syscall_names[] = {
"fork", "exit", "wait", "pipe", "read", "kill", "exec", "fstat", "chdir", "dup", "getpid", "sbrk", "sleep",
"uptime", "open", "write", "mknod", "unlink", "link", "mkdir", "close", "trace"
};
void
@@ -138,6 +145,8 @@ syscall(void)
num = p->trapframe->a7;
if(num > 0 && num < NELEM(syscalls) && syscalls[num]) {
p->trapframe->a0 = syscalls[num]();
if((1 << num) & p->trace_mask)
printf("%d: syscall %s -> %d\n",p->pid, syscall_names[num-1], p->trapframe->a0);
} else {
printf("%d %s: unknown sys call %d\n",
p->pid, p->name, num);