6.S081学习记录-lab2

1、System call tracing

实现一个追踪系统调用的函数,系统中已经提供了一个用户层面的trace程序(user/trace.c),我们要做的就是创建一个新的系统调用来控制跟踪。

trace命令的用法:trace + mask(一个整数,表示需要跟踪的命令) + 待调用的命令 

trace.c的代码如下:(主要功能是将命令行中的参数argv复制到nargv中,除了argv中的前2个参数)

#include "kernel/param.h"
#include "kernel/types.h"
#include "kernel/stat.h"
#include "user/user.h"

int
main(int argc, char *argv[])
{
  int i;
  char *nargv[MAXARG];

  if(argc < 3 || (argv[1][0] < '0' || argv[1][0] > '9')){
    fprintf(2, "Usage: %s mask command\n", argv[0]);
    exit(1);
  }

  if (trace(atoi(argv[1])) < 0) {
    fprintf(2, "%s: trace failed\n", argv[0]);
    exit(1);
  }
  
  for(i = 2; i < argc && i < MAXARG; i++){
    nargv[i-2] = argv[i];
  }
  exec(nargv[0], nargv);
  exit(0);
}

我们需要在proc结构体中添加一个参数mask来存储trace后跟的第一个参数(表示跟踪命令的整数掩码)。

struct proc {
  // ...
  int mask;	   		             // mask for trace system call
};

在kernel/sysproc.c中添加sys_trace函数,从用户栈中取出mask,并保存到当前进程的proc结构体中。

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

由于我们要跟踪的是各个系统调用,因此我们需要在syscall函数(kernel/syscall.c)中添加处理逻辑。

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, syscall_nums[num - 1], p->trapframe->a0);
		}
  } else {
    printf("%d %s: unknown sys call %d\n",
            p->pid, p->name, num);
    p->trapframe->a0 = -1;
  }
}

还有最后一步,添加系统调用编号。

static uint64 (*syscalls[])(void) = {
// ..
[SYS_trace]   sys_trace,
};

static char *syscall_nums[] = {
//..
"trace",
};

2、Sysinfo

添加一个系统调用sysinfo,它收集有关正在运行的系统的信息。

系统已经给出sysinfo将要用到的sysinfo结构体定义:

struct sysinfo {
  uint64 freemem;   // amount of free memory (bytes)
  uint64 nproc;     // number of process
};

在kalloc.c(kernel/kalloc.c)中添加获取空闲存储的函数:

// 遍历空闲链表
uint64
kcountfree(void)
{
  uint64 count = 0;
  struct run *p = kmem.freelist;

  acquire(&kmem.lock);
  while(p){
    count += PGSIZE;
    p = p -> next;
  }
  release(&kmem.lock);
  
  return count;
}

在kernel/proc.c中添加一个函数获取当前系统中状态不是UNUSED的进程数:

// 遍历proc数组以获得状态不为UNUSED的进程数
uint64
countnproc(void)
{
  int n = 0;
  struct proc *p;

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

  return n;
}

在kernel/sysproc.c中添加一个函数调用kcountfree()和countnproc获取数据写入结构体并调用copyout函数(kernel/vm.c)传递到用户空间:

uint64
sys_sysinfo(void)
{
  struct proc *p = myproc();
  uint64 info;

  if(argaddr(0, &info) < 0)
    return -1;
  
  uint64 count[2];
  count[0] = kcountfree();
  count[1] = countnproc();
  if(copyout(p->pagetable, info, (char *)&count, sizeof(count)) < 0)
      return -1;

  return 0;
}

还有一些步骤跟上一题一样,这里便不赘述。

  • 0
    点赞
  • 1
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值