MIT6.s081_Lab2 syscall: System calls

MIT6.s081 Lab2:System calls

这次的实验主要是写两个System Call,分别是tracingSysinfotracing是对系统调用的跟踪,接收一个mask,来对系统调用进行过滤;Sysinfo用来收集系统的一些信息,比如剩余内存、进程的数量。文笔较烂,主要做记录,也希望能给读者一点启发。

代码

1. tracing

因为是为了跟踪在‘mask’作用下的系统调用,每次进行系统调用的时候会进入syscall(),因此需要在syscall函数中将系统调用的名称打印出,我们容易获取到的是系统调用号,所以需要再添加一个数组,记录调用号对应的名称。

if (p->trace_mask & (1 << num)) {
   printf("%d: syscall %s -> %d\n", p->pid, syscall_names[num], p->trapframe->a0);
}

还需要在proc结构体中添加mask,在初始化以及fork等处添加相关代码,维护mask

uint64
sys_trace(void)
{
  int mask;
  
  if(argint(0, &mask) < 0)
    return -1;
  myproc() -> trace_mask = mask;
  return 0;
}

这个实验主要是对整个系统调用过程的理解。

2. Sysinfo

这个需要知道struct sysinfocopyout基本用法,剩下的就是写两个函数获取当前的进程数量和内存信息,然后放到sysinfo函数里即可。

获取剩余内存

uint64 
get_free_memory(void) {
  uint64 free_bytes = 0;
  struct run *current_page;
  acquire(&kmem.lock);
  current_page = kmem.freelist;
  while (current_page) {
    free_bytes += 4096;
    current_page = current_page->next;
  }
  release(&kmem.lock);
  return free_bytes;
}

获取进程数量

uint16
get_proc_num(void)
{
  struct proc *p;
  uint16 proc_num = 0;
  for(p = proc; p < &proc[NPROC]; p++) {
    acquire(&p->lock);
    if(p->state != UNUSED) {
      proc_num++;
    }
    release(&p->lock);
  }
  return proc_num;
}

将获取的数据拷贝回用户空间

uint64
sys_sysinfo(void)
{
  uint64 siaddr;
  struct sysinfo si;
  if(argaddr(0, &siaddr) < 0)
    return -1;
  si.freemem = get_free_memory();
  si.nproc = get_proc_num();
  if(copyout(myproc()->pagetable, siaddr, (char *)&si, sizeof(si)) < 0)
      return -1;
  return 0;
}
posted @ 2025-07-11 20:19  BuerH  阅读(15)  评论(0)    收藏  举报