為xv6添加一個系統調用


1. Overview

要為xv6添加一個系統調用,需要修改以下5個文件:

  • syscall.h
  • syscall.c
  • sysproc.c
  • usys.S
  • user.h

由於Unix v6發行於1975年,下面我們以添加一個返回整數1975的系統調用作為示范來說明如何為xv6添加一個系統調用。

2. syscall.h

打開syscall.h,在相應位置添加下面這一行:

#define SYS_getyear 22

添加后整個文件的內容如下:

// System call numbers
#define SYS_fork    1
#define SYS_exit    2
#define SYS_wait    3
#define SYS_pipe    4
#define SYS_read    5
#define SYS_kill    6
#define SYS_exec    7
#define SYS_fstat   8
#define SYS_chdir   9
#define SYS_dup    10
#define SYS_getpid 11
#define SYS_sbrk   12
#define SYS_sleep  13
#define SYS_uptime 14
#define SYS_open   15
#define SYS_write  16
#define SYS_mknod  17
#define SYS_unlink 18
#define SYS_link   19
#define SYS_mkdir  20
#define SYS_close  21
#define SYS_getyear 22

由此可見,我們添加的getyear是第22號系統調用。

3. syscall.c

syscall.c中添加一個指向該系統調用的函數指針:

[SYS_getyear] sys_getyear

添加后上行后,系統調用的函數指針數組為:

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_getyear] sys_getyear // SYS_getyear == 22
};

可見當用戶程序調用22號系統調用時,會調用sys_getyear這個指針所指向的函數。

因此我們需要自己實現這個函數,在此之前先在syscall.c中添加該函數的原型:

extern int sys_getyear(void);

4. sysproc.c

sysproc.c中添加該調用的實現:

int
sys_getyear(void)
{
	return 1975;
}

可見,該系統調用返回了Unix v6的發布日期1975。

5. usys.S

usys.S中添加下面這一行:

SYSCALL(getyear)

添加后的內容:

#include "syscall.h"
#include "traps.h"

#define SYSCALL(name) \
  .globl name; \
  name: \
    movl $SYS_ ## name, %eax; \
    int $T_SYSCALL; \
    ret

SYSCALL(fork)
SYSCALL(exit)
SYSCALL(wait)
SYSCALL(pipe)
SYSCALL(read)
SYSCALL(write)
SYSCALL(close)
SYSCALL(kill)
SYSCALL(exec)
SYSCALL(open)
SYSCALL(mknod)
SYSCALL(unlink)
SYSCALL(fstat)
SYSCALL(link)
SYSCALL(mkdir)
SYSCALL(chdir)
SYSCALL(dup)
SYSCALL(getpid)
SYSCALL(sbrk)
SYSCALL(sleep)
SYSCALL(uptime)
SYSCALL(getyear)

6. user.h

為了能夠讓用戶程序訪問到getyear系統調用,我們需要在user.h中聲明該調用:

int getyear(void);

添加后的系統調用聲明:

// system calls
int fork(void);
int exit(void) __attribute__((noreturn));
int wait(void);
int pipe(int*);
int write(int, const void*, int);
int read(int, void*, int);
int close(int);
int kill(int);
int exec(char*, char**);
int open(const char*, int);
int mknod(const char*, short, short);
int unlink(const char*);
int fstat(int fd, struct stat*);
int link(const char*, const char*);
int mkdir(const char*);
int chdir(const char*);
int dup(int);
int getpid(void);
char* sbrk(int);
int sleep(int);
int uptime(void);
int getyear(void); 

7. 測試getyear

完成上述步驟,一個系統調用就已經創建好了,現在來編寫一個用戶程序來測試以下該系統調用。

創建一個用戶程序:getyear.c

#include "types.h"
#include "stat.h"
#include "user.h"

int
main(void)
{
        printf(1, "Note: Unix v6 was released in year %d\n", getyear());
        exit();
}

Makefile中的UPROGS中添加_getyear:

UPROGS=\
        _cat\
        _echo\
        _forktest\
        _getyear\
        _grep\
        _hello\
        _init\
        _kill\
        _ln\
        _ls\
        _mkdir\
        _rm\
        _sh\
        _stressfs\
        _usertests\
        _wc\
        _zombie\

現在啟動xv6,運行getyear程序:

Booting from Hard Disk..xv6...
cpu1: starting 1
cpu0: starting 0
sb: size 1000 nblocks 941 ninodes 200 nlog 30 logstart 2 inodestart 32 bmap start 58
init: starting sh
$ getyear
Note: Unix v6 was released in year 1975

命令行里順利地顯示出了預期的Unix v6的發布日期。


免責聲明!

本站轉載的文章為個人學習借鑒使用,本站對版權不負任何法律責任。如果侵犯了您的隱私權益,請聯系本站郵箱yoyou2525@163.com刪除。



 
粵ICP備18138465號   © 2018-2025 CODEPRJ.COM