xv6-lab2: system call

trace

Reference

$ trace
Jason was born in year 1999

So, Now we can add more code and test trace function.
here are the files we need to modify:

write sys_trace() to input the mask:

// for sys_trace definition
uint64
sys_trace(void)
{
  int mask;
  if(argint(0,&mask) < 0){  // transfer 'char' to 'int'
    return -1;
  }
  struct proc *p = myproc();
  p->mask = mask;
  printf("input mask == %d\n", mask);
  return 0;
}

this function can surely get 32 at trace() in the trace.c

$ trace 32 grep hello README
input mask == 32
6 :  syscall read 1023
6 :  syscall read 968
6 :  syscall read 235
6 :  syscall read 0
//syscall.c add
static char *syscall_name[] = {
  "", "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){  // AND operation, bit movement
      // syscall num == 1 AND mask == 1
      printf("%d :  syscall %s %d\n",
            p->pid, syscall_name[num], p->trapframe->a0);
      // [pid]: syscall [call_name] [return value]
    }
  } else {
    printf("%d %s: unknown sys call %d\n",
            p->pid, p->name, num);
    p->trapframe->a0 = -1;
  }
}

So far, trace function finish. but there is still one question. why trace() has no implementation but still work?
As I know, I’ve not written it. So, I go back to lab1, and see the hint:

  • See kernel/sysproc.c for the xv6 kernel code that implements the sleep system call (look for sys_sleep), user/user.h for the C definition of sleep callable from a user program, and user/usys.S for the assembler code that jumps from user code into the kernel for sleep.
.global fork
fork:
 li a7, SYS_fork
 ecall
 ret

this assembly means fork() can trigger SYS_fork pointer address, then the address->a7, sys_fork therefore run in a privileged state.

sysinfo

first run after basic configuration:

$ sysinfotest
sysinfotest: start
FAIL: sysinfo succeeded with bad argument

Now, we need to modify the sys_sysinfo to get system’s free memory & process amount.

//sysproc.c
// give system information: free memory & process
// info_pointer is a user virtual address, pointing to a struct sysinfo.
uint64
sys_sysinfo(void)
{
  uint64 info_pointer;
  struct proc *p = myproc();
  struct sysinfo info;
  info.freemem = freemem();
  info.nproc = nproc();
  argaddr(0, &info_pointer);
  if(copyout(p->pagetable, info_pointer, (char *)&info, sizeof(info)) < 0)
      return -1;
  return 0;
}

but, freemem() and nproc() haven’t been implemented.

// kalloc.c
uint64
freemem(void)
{
  struct run *r;
  uint64 count = 0;
  acquire(&kmem.lock);
  r = kmem.freelist;
  while(r){
    count++;
    r = r->next;
  }
  release(&kmem.lock);
  return PGSIZE * count;
}

//proc.c
// nproc
uint64
nproc(void)
{
  struct proc *p;
  uint64 count = 0;
  for(p = proc; p < &proc[NPROC]; p++) {
    acquire(&p->lock);
    if(p->state != UNUSED) {
      count++;
    }
    release(&p->lock);
  }
  return count;
}
  • reference of writting nproc & freemem
// reference of writting nproc
// Look in the process table for an UNUSED proc.
// If found, initialize state required to run in the kernel,
// and return with p->lock held.
// If there are no free procs, or a memory allocation fails, return 0.
static struct proc*
allocproc(void)
{
  struct proc *p;

  for(p = proc; p < &proc[NPROC]; p++) {
    acquire(&p->lock);
    if(p->state == UNUSED) {
      goto found;
    } else {
      release(&p->lock);
    }
  }
  return 0;

found:
  p->pid = allocpid();
  p->state = USED;

  // Allocate a trapframe page.
  if((p->trapframe = (struct trapframe *)kalloc()) == 0){
    freeproc(p);
    release(&p->lock);
    return 0;
  }

  // An empty user page table.
  p->pagetable = proc_pagetable(p);
  if(p->pagetable == 0){
    freeproc(p);
    release(&p->lock);
    return 0;
  }

  // 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;

  return p;
}
// Free the page of physical memory pointed at by v,
// which normally should have been returned by a
// call to kalloc().  (The exception is when
// initializing the allocator; see kinit above.)
void
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;

  acquire(&kmem.lock);
  r->next = kmem.freelist;
  kmem.freelist = r;
  release(&kmem.lock);
}

result:(adding test code in sysinfortest.c, we can see free memory & process number)

$ sysinfotest
sysinfotest: start
free memory = 133128192
num of process = 3
sysinfotest: OK
  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值