1. 程式人生 > >MIT6.828 HW3: xv6 system calls

MIT6.828 HW3: xv6 system calls

第1部分:System cakk tracing
  主要任務是在進行系統呼叫時,打印出系統呼叫的名字和返回值。
  當你實現後,啟動時輸出如下(執行sh.c):

...
fork -> 2
exec -> 0
open -> 3
close -> 0
$write -> 1
 write -> 1

  實現思路:
  系統呼叫函式在syscall.c中,主要是在syscall函式內新增printf語句。

    //系統呼叫對應名字陣列
  static char syscalls_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", [SYS_date] "date", }; void syscall(void) { int num; num = proc->tf->eax; //獲取系統呼叫號 if(num > 0 && num < NELEM(syscalls) && syscalls[num]) { proc
->tf->eax = syscalls[num](); //儲存系統呼叫返回值 //cprintf("%s -> %d\n", syscalls_name[num], proc->tf->eax); } else { cprintf("%d %s: unknown sys call %d\n", proc->pid, proc->name, num); proc->tf->eax = -1; } }

  challenge:在列印時,同時輸出系統呼叫函式的引數
  主要思路:考察函式呼叫過程中的堆疊變化,esp調esp+4調esp+4+4*n儲存的是第n個引數(整型或者指標)。由於不同系統呼叫的引數不同,所以需要針對系統呼叫函式的引數型別進行判斷,然後再獲取列印。獲取引數可以參考syscall.c檔案中argcint函式的實現。(並未在程式碼實現)

第2部分:Date system call
  主要任務是實現1個系統呼叫列印日期和時間。
  實現思路:要實現1個系統呼叫主要步驟是新增系統呼叫號和具體的系統呼叫函式。可以仿照uptime系統呼叫。(使用grep -r * .[chS]檢視具體的修改處)
  這裡寫圖片描述
  1.在syscall.h中新增系統呼叫號
  2.在user.h中新增使用者態函式的定義
  3.在usys.S中新增使用者態函式的實現
  4.在syscall.c中新增系統呼叫函式的外部宣告
  5.在sysproc.c中新增系統呼叫函式的實現
   系統呼叫函式具體實現程式碼:

//sysproc.c
//cmostime定義在lapic.c中
int
sys_date(void)
{
  struct rtcdate *r;

  if (argptr(0, (void *)&r, sizeof(*r)) < 0)
          return -1;
  cmostime(r);  //從cmos中獲取時間
  return 0;
}

  challenge:實現dup2系統呼叫
  主要思路:可仿照dup系統呼叫的實現(dup和dup2)

int
sys_dup2(void)
{
  struct file *f1, *f2;
  int fd1, fd2;

  if(argfd(0, &fd1, &f1) < 0 || argint(1, &fd2) < 0)
    return -1;
  if(fd2 < 0 || fd2 >= NOFILE)
    return -1;
  if (fd1 != fd2) {   //如果新的fd和舊的fd不同
      f2 = proc->ofile[fd2];
      if (f2)  //判斷新的fd對應的檔案是否開啟,若開啟則關閉
        fileclose(f2);  
      proc->ofile[fd2] = f1;
      filedup(f1);
  }
  return fd2;
}