MIT 6s081 lab2:system calls

Lab2 : system calls

作业地址:Lab: System calls (mit.edu)

  • Add $U/_trace to UPROGS in Makefile
  • add a prototype for the system call to user/user.h, a stub to user/usys.pl, and a syscall number to kernel/syscall.h. The Makefile invokes the perl script user/usys.pl
  • Add a sys_trace() function in kernel/sysproc.c that implements the new system call by remembering its argument in a new variable in the proc structure (see kernel/proc.h). The functions to retrieve system call arguments from user space are in kernel/syscall.c, and you can see examples of their use in kernel/sysproc.c.
  • Modify fork() (see kernel/proc.c) to copy the trace mask from the parent to the child process.

1、在用户层声明接口

2、在内核中,把用户调用的参数读入,然后传给进程结构体的参数

3、在fork中,把父进程的参数拷贝给子进程

4、在syscall统一的接口中(通过确定系统调用的编号,作为函数指针数组中的索引,进而调用到具体的函数,函数调用的参数从进程的参数中获取argint函数

system call tracing(moderate)

用trace的mask对系统调用进行跟踪,打印进程号,系统调用名,和系统调用返回值

先定义系统调用号

/* kernel/syscall.h add call number */
#define SYS_trace  22
#define SYS_sysinfo 23

用数组存储系统调用号和函数指针的映射,用于后续调用

/* kernel/syscall.c add */
static uint64 (*syscalls[])(void) = {
[SYS_fork]    sys_fork,
[SYS_exit]    sys_exit,
[SYS_wait]    sys_wait,
[SYS_pipe]    sys_pipe,
[SYS_read]    sys_read,
[SYS_kill]    sys_kill,
[SYS_exec]    sys_exec,
[SYS_fstat]   sys_fstat,
[SYS_chdir]   sys_chdir,
[SYS_dup]     sys_dup,
[SYS_getpid]  sys_getpid,
[SYS_sbrk]    sys_sbrk,
[SYS_sleep]   sys_sleep,
[SYS_uptime]  sys_uptime,
[SYS_open]    sys_open,
[SYS_write]   sys_write,
[SYS_mknod]   sys_mknod,
[SYS_unlink]  sys_unlink,
[SYS_link]    sys_link,
[SYS_mkdir]   sys_mkdir,
[SYS_close]   sys_close,

[SYS_trace]   sys_trace,
[SYS_sysinfo] sys_sysinfo,
};

static char* syscalls_name[] = {
[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",

[SYS_trace]   "trace",
[SYS_sysinfo] "sys_sysinfo",
};
void
syscall(void)
{
  int num;
  struct proc *p = myproc();

  num = p->trapframe->a7; // 读取系统调用号
  if(num > 0 && num < NELEM(syscalls) && syscalls[num]) {
    /* printf the system call debug message */
    p->trapframe->a0 = syscalls[num]();  //记录返回值
    if(p->mask & (1 << num))
    {
      printf("%d: syscall %s -> %d\n", p->pid, syscalls_name[num],p->trapframe->a0); // 打印trace信息
    }
  } else {
    printf("%d %s: unknown sys call %d\n",
            p->pid, p->name, num);
    p->trapframe->a0 = -1;
  }
}

Sysinfo (moderate)

用sysinfo系统调用,记录当前的进程数量和空闲内存

定义工具方法get_nproc获取进程数量,get_free_memory获取空闲的内存数量

// 根据全局进程数组中进程状态不为
int get_nproc(void)
{
    // struct proc proc[NPROC]; // 全局进程数组
    int num = 0;
    for(int i = 0; i < NPROC; i++) {
        acquire(&(proc[i].lock));
        if(proc[i].state != UNUSED)
            num++;
        release(&(proc[i].lock));
    }
    return num;
}
// 空闲内存是采用链表进行维护的,链表的每个节点代表一个页的空间,最后一个空闲页的next必然为NULL
int get_free_memory(void)
{
    struct run *r;
    acquire(&kmem.lock);
    int num = 0;
    /* freelist开始计算一直链表访问,直到内存终点 */
    r = kmem.freelist;
    while(r)
    {
        num += PGSIZE;
        r = r->next;
    }
    release(&kmem.lock);

    return num;
}
uint64
sys_sysinfo(void)
{
  /* learn sys_fstat() and filestat() to copyout */
  
  uint64 addr; // user pointer to struct sysinfo

  if(argaddr(0, &addr) < 0) // 读取从用户空间传入的结构体指针参数的地址
    return -1;
  // addr is a user virtual address, pointing to a struct sinfo.
  struct proc *p = myproc();
  struct sysinfo sinfo;
  // collect the amount of free memory
  sinfo.freemem = get_free_memory();

  // collect the number of processes
  sinfo.nproc = get_nproc();
  if(copyout(p->pagetable, addr, (char *)&sinfo, sizeof(sinfo)) < 0)
    return -1;
  
  return 0;
}

提交

make grade
$ make qemu-gdb
trace 32 grep: OK (2.8s) 
== Test trace all grep == 
$ make qemu-gdb
trace all grep: OK (0.6s) 
== Test trace nothing == 
$ make qemu-gdb
trace nothing: OK (0.9s) 
== Test trace children == 
$ make qemu-gdb
trace children: OK (9.1s) 
== Test sysinfotest == 
$ make qemu-gdb
sysinfotest: OK (1.4s) 
== Test time == 
time: OK 
Score: 35/35
  • 7
    点赞
  • 7
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值