xv6 syscall实验

Syscall

文章目录

  • Syscall
    • 一、实验要求
      • Part One: System call tracing
      • Part Two: Date system call
    • 二、实验操作
      • Part one
      • Part Two

request

一、实验要求

Part One: System call tracing

Your first task is to modify the xv6 kernel to print out a line for each system call invocation. It is enough to print the name of the system call and the return value; you don’t need to print the system call arguments.
When you’re done, you should see output like this when booting xv6:

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

That’s init forking and execing sh, sh making sure only two file descriptors are open, and sh writing the $ prompt. (Note: the output of the shell and the system call trace are intermixed, because the shell uses the write syscall to print its output.)

Hint: modify the syscall() function in syscall.c.
Optional challenge: print the system call arguments.

Part Two: Date system call

Your second task is to add a new system call to xv6. The main point of the exercise is for you to see some of the different pieces of the system call machinery. Your new system call will get the current UTC time and return it to the user program. You may want to use the helper function, cmostime() (defined in lapic.c), to read the real time clock. date.h contains the definition of the struct rtcdate struct, which you will provide as an argument to cmostime() as a pointer.

You should create a user-level program that calls your new date system call; here’s some source you should put in 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();
  }

  // your code to print the time in any format you like...

  exit();
}

In order to make your new date program available to run from the xv6 shell, add _date to the UPROGS definition in Makefile.

Your strategy for making a date system call should be to clone all of the pieces of code that are specific to some existing system call, for example the “uptime” system call. You should grep for uptime in all the source files, using *grep -n uptime .[chS].

When you’re done, typing date to an xv6 shell prompt should print the current UTC time.

Write down a few words of explanation for each of the files you had to modify in the process of creating your date system call.

Optional challenge: add a dup2() system call and modify the shell to use it.
*syscall.h:

二、实验操作

Part one

要实现系统调调用时打印系统调用的名称和参数,我们需要修改syscall.csyscalll.h文件

然后我们先看一下syscall.c的代码

// 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

不难看出,这段代码是对xv6 21个常见系统调用的宏定义,我们要想实现打印调用名称和参数,可以在syscall.c设置和系统调用的相同的编号和名称相对应的数组

#include "x86.h"
#include "syscall.h"

// 以下为添加的内容
static char SYS_call_names[][6] = {
        [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()函数,使其实现当系统调用时打印对应的名称和编号

$make qemu (或make qemu-nox)
//make qemu-nox是将qemu固定在linux下,在串口终端中启动Qemu

运行结果如下图
[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-C5kxiRPK-1571208580659)(partone.png)]

void syscall(void)
····
    curproc ->tf->eax = syscall[numm]();
// 以下为添加的内容
        cprintf("\tSYS_call: %s\tid: %d\n", SYS_call_names[num], num);
// 以上为添加的内容
}
else
···

到这里第一个小部分就完成了,这部分其实很简单就是在syscall调用函数是加入了一句打印代码使其实现功能

  • 在这没学过c语言的可能会疑惑是printf的基本语法,我在下面简单介绍一下:
    首先在这里的**cprintf()我认为和printf()**的基本用法是一样的。
    printf()函数调用格式:printf(“格式化字符串”,输出表列)。格式化字符串包含三种对象,为:
    (1)字符串常量
    (2)格式化控制字符串
    (3)转义字符
    字符串常量原样输出,在显示中起提示作用。输出表列中给出了各个输出项,要求格式控制字符串和各输出项在数量和类型上应该一一对应。其中格式控制字符串是以%开头的字符串,在%后面跟有各种格式控制符,以说明输出数据的类型、宽度、精度等。
    格式化控制字符串:
    %[标志][最小宽度][.精度][类型长度]类型
    示例:

    printf("%5d\n",1000);               //默认右对齐,左边补空格
    
    output:
    ` `1000
    

    常用转义字符:
    \n :回车符
    \t :横向制表符
    \v:纵向制表符

Part Two

  • 在各种文件里添加第22个系统调用sys_date
    1.syscall.h:

     #define SYS_date 22
    
    

    2.syscall.c:

    [SYS_date]  " date"
    };
    
    ···
    extern int sys_date(void);
    
    ···
    [SYS_date] sys_date
    
    

    3.user.h文件添加用户态函数

    int sleep(int);
    int uptime(void);
    // 以下为添加内容
    int date(struct rtcdate*);
    // 以上为添加内容
    
    

    4.usys.S添加用户态函数的实现

    SYSCALL(date)
    

    5.sysproc.c添加系统调用函数

    int
    sys_date(struct rtcdate *r)
    {
        if (argptr(0, (void *)&r, sizeof(*r)) < 0)
           return -1;
           cmostime(r);  //从cmos中获取时间
           return 0;
     }
    
    

至此,就完成了添加系统调用函数 date()
最后,我们需要添加使用这个系统调用函数的方法
新建文件 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();
    }

    // your code to print the time in any format you like...
    printf(1, "%d-%d %d %d:%d:%d\n", r.month, r.day, r.year, r.hour, r.minute, r.second);
    //输出格式可以随意定义
    exit();
}

6.最后不要忘了在MakeFile添加UPROGS对应的命令:

_big\
# 以下为添加内容
    _date\
# 以上为添加内容
  • 到此就完成了所有程序的修改,然后我们运行
make qemu
//然后输入date
$date
  • 但是结果却并不和预期一样
    [外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-y0R4MoKv-1571208580662)(parttwo.png)]
    然后我们发现其实这是之前第一部分系统调用造成的,虽然没有达到我们的预期但是却能够清晰的显现每个输出的系统调用命令
    然后我们把第一部分的系统调用注释掉就好了
    [外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-dCvkrWaf-1571208580664)(partthree.png)]
    最后成功的实现了我们的预期!

你可能感兴趣的:(xv6,syscall,MIT,linux)