MIT 6.S081---Lab: system calls

环境配置

对gdb配置有问题的可以参考MIT 6.S081 Lab 0: 实验配置, 调试及测试
列几个常用的指令:

//以gdb模式启动qemu
make CPUS=1 qemu-gdb

//在另一个窗口开启gdb
riscv64-unknown-elf-gdb

//不多说,神器
layout split

实验

System call tracing (moderate)

xv6用perl脚本做到内核代码函数和用户函数的自动对应,感觉挺有趣的,但感觉要看懂要很久。

//user/usys.pl
...
entry("sleep");
entry("uptime");
entry("trace");//新增

//kernel/syscall.h
#define SYS_close  21
#define SYS_trace  22//新增

//kernel/sysproc.c
uint64 
sys_trace(void) 
{
  int mask;

  if (argint(0, &mask) < 0) 
    return -1;
  myproc()->mask = mask;
  return 0;
}

//kernel/proc.h
struct proc {
  struct spinlock lock;

  // p->lock must be held when using these:
  enum procstate state;        // Process state
  struct proc *parent;         // Parent process
  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

  // 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)
  uint64 mask;                    // trace mask
};

//kernel/proc.c
allocproc(void)
{
  struct proc *p;

  ...
  p->mask = 0;//新增
  return p;
}

int
fork(void)
{
  int i, pid;
  struct proc *np;
  struct proc *p = myproc();

  // Allocate process.
  if((np = allocproc()) == 0){
    return -1;
  }

  // Copy user memory from parent to child.
  if(uvmcopy(p->pagetable, np->pagetable, p->sz) < 0){
    freeproc(np);
    release(&np->lock);
    return -1;
  }
  np->sz = p->sz;

  np->parent = p;
  np->mask = p->mask;//新增


  return pid;
}

//kernel/syscall.c
extern uint64 sys_trace(void); //新增

static char* sysnames[] = {"", "fork", "exit", "wait", "pipe", "read", "kill", "exec",
  "fstat", "chdir", "dup", "getpid", "sbrk", "sleep", "uptime", "open", "write",
  "mknod", "unlink", "link", "mkdir", "close", "trace"};

void
syscall(void)
{
  int num;
  struct proc *p = myproc();
 
  num = p->trapframe->a7;
  if(num > 0 && num < NELEM(syscalls) && syscalls[num]) {
    p->trapframe->a0 = syscalls[num]();
    if ((p->mask & (1 << num)) > 0) {
      printf("%d: syscall %s -> %d\n", p->pid, sysnames[num], p->trapframe->a0);
    }
  } else {
    printf("%d %s: unknown sys call %d\n",
            p->pid, p->name, num);
    p->trapframe->a0 = -1;
  }
}

疑问:之前总是出现如下问题(改了allocproc后还是这样),后面代码一行没改又好了,很奇怪
MIT 6.S081---Lab: system calls_第1张图片

Sysinfo (moderate)

几乎流程与上个相同,就是需要注意一些细节,下面仅列出部分关键代码。

//kernel/kalloc.c
void
kinit()
{
  struct sysinfo* info = mysysinfo();
  info->freemem = 0;
  initlock(&kmem.lock, "kmem");
  freerange(end, (void*)PHYSTOP);
}

kfree(void *pa)
{
  struct run *r;
  if(((uint64)pa % PGSIZE) != 0 || (char*)pa < end || (uint64)pa >= PHYSTOP)
    panic("kfree");

  // Fill with junk to catch dangling refs.
  memset(pa, 1, PGSIZE);

  r = (struct run*)pa;

  struct sysinfo* info = mysysinfo();//新增
  acquire(&kmem.lock);
  r->next = kmem.freelist;
  kmem.freelist = r;
  info->freemem += PGSIZE;//新增
  release(&kmem.lock);
}

kalloc(void)
{
  struct run *r;
  struct sysinfo* info = mysysinfo();

  acquire(&kmem.lock);
  r = kmem.freelist;
  if(r)
  if(r) {
    kmem.freelist = r->next;
    info->freemem -= PGSIZE;//新增
  }
  release(&kmem.lock);

//kernel/proc.c
struct sysinfo sysinfo;
struct sysinfo* 
mysysinfo(void)
{
  struct sysinfo* info = &sysinfo;
  return info;
};

allocproc(void)
{
  struct proc *p;
  struct sysinfo* info;
  for(p = proc; p < &proc[NPROC]; p++) {
    acquire(&p->lock);
    if(p->state == UNUSED) {
		...
    return 0;
  }
  info = mysysinfo();
  // Set up new context to start executing at forkret,
  // which returns to user space.
  memset(&p->context, 0, sizeof(p->context));
  p->context.ra = (uint64)forkret;
  p->context.sp = p->kstack + PGSIZE;
  p->mask = 0;
  info->nproc++;
  return p;
}

//kernel/sysproc.c
uint64 
sys_sysinfo(void) 
{
  uint64 addr;
  if(argaddr(0, &addr) < 0)
    return -1;
  struct proc *p = myproc();
  struct sysinfo* info = mysysinfo();
  if(copyout(p->pagetable, addr, (char *)info, sizeof(*info)) < 0)
    return -1;
  return 0;
}

你可能感兴趣的:(#,6.S081,c语言)