MIT 6.828 System calls

asm volatile 内嵌汇编指令语法

System call tracing

增加一个trace系统调用,用户在其他命令前输入trace后,跟踪记录命令使用的相关系统调用(mask指示要跟踪哪些)

$ trace mask command [args]

步骤

1、在Makefile中增加 $U/_trace 到UPROGS,用于编译用户程序user/trace.c

2、在user/user.h中增加trace系统调用的原型

int trace(int);

3、在user/usys.pl中增加trace的汇编指令生成entry

entry("trace");

4、在kernel/syscall.h中增加trace系统调用的编号

#define SYS_sysinfo 23

5、在kernel/proc.h中的proc结构体定义新成员tracemask,保存mask

// Per-process state
struct proc {
  struct spinlock lock;

  // p->lock must be held when using these:
  enum procstate state;        // Process state
  void *chan;                  // If non-zero, sleeping on chan
  int killed;                  // If non-zero, have been killed
  int xstate;                  // Exit status to be returned to parent's wait
  int pid;                     // Process ID

  // wait_lock must be held when using this:
  struct proc *parent;         // Parent process

  // these are private to the process, so p->lock need not be held.
  uint64 kstack;               // Virtual address of kernel stack
  uint64 sz;                   // Size of process memory (bytes)
  pagetable_t pagetable;       // User page table
  struct trapframe *trapframe; // data page for trampoline.S
  struct context context;      // swtch() here to run process
  struct file *ofile[NOFILE];  // Open files
  struct inode *cwd;           // Current directory
  char name[16];               // Process name (debugging)

  int tracemask;               // For system call lab, remember the trace() argument
};

6、在kernel/proc.c中的fork()函数增加复制父进程的mask到子进程,注意要在加锁的时候

7、在kernel/sysproc.c中定义sys_trace函数,实际处理系统调用

uint64
sys_trace(void) {
    int mask;

    if (argint(0, &mask) < 0) {  // 从trap frame中获取用户的参数
        return -1;
    }

    myproc()->tracemask = mask;
    return 0;
}

8、在kernel/syscall.c中增加此系统调用到system call table中,用来映射系统调用序号SYS_trace到sys_trace函数

Sysinfo

步骤1、2、3、4、8与上相同

在kernel/sysproc.c中实现sys_sysinfo函数时,需要参考kernel/sysfile.c和kernel/file.c中对用户空间地址的访问(写,copyout()函数)

uint64
sys_sysinfo(void) {
    struct proc *p = myproc();
    uint64 infoaddr; // address of the user argument
    if (argaddr(0, &infoaddr) < 0) {
        return -1;
    }
    struct sysinfo info;
    info.freemem = freespaces();
    info.nproc = procnum();

    if(copyout(p->pagetable, infoaddr, (char *)&info, sizeof(info)) < 0)
        return -1;
    return 0;
}

在kernel/kalloc.c中实现获取空闲空间大小的函数

// Returns the free space size of bytes
int
freespaces(void) {
    struct run *r;
    int freenum = 0;

    acquire(&kmem.lock);
    r = kmem.freelist;
    while (r) {
        freenum++;
        r = r->next;
    }
    release(&kmem.lock);
    return freenum * PGSIZE;
}

在kernel/proc.c中实现获取正在使用的进程的数目的函数

// Returns the number of processes whose state is not UNUSED
int procnum(void) {
    struct proc* p;
    int nums = 0;

    for (p = proc; p < &proc[NPROC]; p++) {
        if (p->state != UNUSED) {
            nums++;
        }
    }
    return nums;
}

在kernel/defs.h中增加上面两个函数的声明

完成实现kernel/sysproc.c中的sys_sysinfo