MIT6.s081 lab System calls

lab System calls

0、time

4 hours

1、trace

// 1.在user/user.h中加上trace函数定义
int trace(int);

// 2.在user/usys.pl中加上trace的entry脚本
entry("trace");

// 3.在kernel/proc.h的struct proc定义中加上teacemask标志
uint64 tracemask;            // bit mask for tracing

// 4.kernel/proc.c中有两个函数需要改动
1.
static struct proc*
allocproc(void)
{
    ...
    //初始化tracemask(我们要添加的语句)
    p->tracemask = 0;
    return p;
}
allocproc函数的作用是找一个没使用过的proc,所以在一个进程创建时,此函数一定会执行,我们的目的就是在创建进程时就把tracemask初始化为0

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

  //继承父进程的trace mask(我们要添加的语句)
  np->tracemask = p->tracemask;

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

// 5.实现kernel/sysproc.c中的sys_trace函数
uint64
sys_trace(void) {
    int trace_sys_mask;
    if (argint(0, &trace_sys_mask) < 0)//从a0寄存器获取参数
        return -1;
    myproc()->tracemask |= trace_sys_mask;
    return 0;
}

// 6.修改kernel/syscall.h,syscall.c的某些定义
1.
#define SYS_trace  22

2.
static uint64 (*syscalls[])(void) = {
...
[SYS_trace]   sys_trace,//添加这行
};
//添加下面这个字符串数组
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",
        "sysinfo"
};

// 7.修改kernel/syscall.函数syscall
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]();//返回值存在a0寄存器中
    if (p->tracemask & (1 << num))
        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;
  }
}

//执行流
	user/trace.c -> trace()
    user/usys.pl -> entry
    kernel/syscall.c -> syscall()
    syscall() -> kernel/sysproc.c:sys_trace()

2、sysinfo

1.获取空闲内存大小
    uint64 kfreemem(void) {
    struct run *r;
    uint64 freesize = 0;

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

2.获取正在使用的进程数
    uint64 kfreemem(void) {
    struct run *r;
    uint64 freesize = 0;

    acquire(&kmem.lock);
    r = kmem.freelist;
    while (r) {
        freesize += PGSIZE;
        r = r->next;
    }
    release(&kmem.lock);
    return freesize;
}
3.sys_sysinfo
    uint64
sys_sysinfo(void) {
    struct proc *my_proc = myproc();
    uint64 p;
    if (argaddr(0, &p) < 0)//读取a0寄存器内容放到p中:此时存的是sysinfo结构体地址
        return -1;

    struct sysinfo s;
    s.freemem = kfreemem();
    s.nproc = procnum();

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

3、总结

必须将代码的执行流理顺

posted @   silly19  阅读(9)  评论(0编辑  收藏  举报
相关博文:
阅读排行:
· 无需6万激活码!GitHub神秘组织3小时极速复刻Manus,手把手教你使用OpenManus搭建本
· Manus爆火,是硬核还是营销?
· 终于写完轮子一部分:tcp代理 了,记录一下
· 别再用vector<bool>了!Google高级工程师:这可能是STL最大的设计失误
· 单元测试从入门到精通
点击右上角即可分享
微信分享提示