Skip to content

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);