Skip to content

Sysinfo (moderate)

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

在Makefile的UPROGS中添加$U/_sysinfotest

diff --git a/Makefile b/Makefile
--- a/Makefile
+++ b/Makefile
@@ -150,7 +150,7 @@ UPROGS=\
        $U/_wc\
        $U/_zombie\
        $U/_trace\

       $U/_sysinfotest\
 
 ifeq ($(LAB),trap)
 UPROGS += \

要在user/user.h中声明sysinfo()的原型

需要预先声明struct sysinfo的存在:

c
struct sysinfo;
int sysinfo(struct sysinfo *);

diff --git a/user/user.h b/user/user.h
--- a/user/user.h
+++ b/user/user.h
@@ -1,5 +1,6 @@
 struct stat;
 struct rtcdate;
struct sysinfo;
 
 // system calls
 int fork(void);
@@ -24,6 +25,7 @@ char* sbrk(int);
 int sleep(int);
 int uptime(void);
 int trace(int);
int sysinfo(struct sysinfo *);
 
 // ulib.c
 int stat(const char*, struct stat*);

当运行make qemu时,user/sysinfotest.c将会编译失败

遵循和上一个作业一样的步骤添加sysinfo系统调用

diff --git a/user/usys.pl b/user/usys.pl
--- a/user/usys.pl
+++ b/user/usys.pl
@@ -36,4 +36,5 @@ entry("getpid");
 entry("sbrk");
 entry("sleep");
 entry("uptime");
entry("trace");
\ No newline at end of file
entry("trace");
entry("sysinfo");
\ No newline at end of file
diff --git a/kernel/syscall.h b/kernel/syscall.h
--- a/kernel/syscall.h
+++ b/kernel/syscall.h
@@ -20,4 +20,5 @@
 #define SYS_link   19
 #define SYS_mkdir  20
 #define SYS_close  21
#define SYS_trace  22
\ No newline at end of file
#define SYS_trace  22
#define SYS_sysinfo 23
\ No newline at end of file
diff --git a/kernel/syscall.c b/kernel/syscall.c
--- a/kernel/syscall.c
+++ b/kernel/syscall.c
@@ -105,6 +105,7 @@ extern uint64 sys_wait(void);
 extern uint64 sys_write(void);
 extern uint64 sys_uptime(void);
 extern uint64 sys_trace(void);
extern uint64 sys_sysinfo(void);
 
 static uint64 (*syscalls[])(void) = {
 [SYS_fork]    sys_fork,
@@ -129,6 +130,7 @@ static uint64 (*syscalls[])(void) = {
 [SYS_mkdir]   sys_mkdir,
 [SYS_close]   sys_close,
 [SYS_trace]   sys_trace,
[SYS_sysinfo] sys_sysinfo,
 };
 
 static char *syscall_names[] = {

一旦修复了编译问题,就运行sysinfotest;但由于您还没有在内核中实现系统调用,执行将失败。

sysinfo需要将一个struct sysinfo复制回用户空间

请参阅sys_fstat()(kernel/sysfile.c)和filestat()(kernel/file.c)以获取如何使用copyout()执行此操作的示例。

diff --git a/kernel/sysproc.c b/kernel/sysproc.c
--- a/kernel/sysproc.c
+++ b/kernel/sysproc.c
@@ -6,6 +6,10 @@
 #include "memlayout.h"
 #include "spinlock.h"
 #include "proc.h"
#include "sysinfo.h"

int get_nproc();
int get_freemen();
 
 uint64
 sys_exit(void)
@@ -108,3 +112,23 @@ sys_trace(void)
   p->trace_mask=mask;
   return 0;
 }

uint64
sys_sysinfo(void){
  struct proc *p = myproc();
  struct sysinfo st;
  uint64 addr;

  st.nproc=get_nproc();
  st.freemem=get_freemen();

  //参阅sys_fstat()(kernel/sysfile.c)
  if(argaddr(0, &addr) < 0)//获取指向结构体的指针,并存储在 st 变量中
    return -1;

  //参阅filestat()(kernel/file.c)
  if(copyout(p->pagetable, addr, (char *)&st, sizeof(st)) < 0)//将 st 结构体的内容从内核空间复制到用户空间的指定地址 addr
    return -1;

  return 0;
}
\ No newline at end of file

要获取空闲内存量,在kernel/kalloc.c中添加一个函数

diff --git a/kernel/kalloc.c b/kernel/kalloc.c
--- a/kernel/kalloc.c
+++ b/kernel/kalloc.c
@@ -80,3 +80,18 @@ kalloc(void)
     memset((char*)r, 5, PGSIZE); // fill with junk
   return (void*)r;
 }

int get_freemen(void){
  int count=0;
  struct run *r;

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

  return count * PGSIZE;
}
\ No newline at end of file

要获取进程数,在kernel/proc.c中添加一个函数

diff --git a/kernel/proc.c b/kernel/proc.c
--- a/kernel/proc.c
+++ b/kernel/proc.c
@@ -696,3 +696,16 @@ procdump(void)
     printf("\n");
   }
 }

int get_nproc(void){
  int count=0;
  struct proc *p;
  for(p = proc; p < &proc[NPROC]; p++) {
    acquire(&p->lock);
    if(p->state != UNUSED) {
      count++;
    }
    release(&p->lock);
  }
  return count;
}
\ No newline at end of file