MIT6.828 Lab2-3 Sysinfo

目录

  • 实验内容
  • 已有的代码
  • 修改部分

实验内容

  • 添加一个系统调用sysinfo用以收集系统运行时的信息
  • sysinfo只使用了一个参数,详见kernel/sysinfo.h(struct sysinfo)即记录了状态的结构体
  • 使用内核填充struct sysinfo
  • 提供了sysinfotest用以测试效果,通过会输出sysinfotest: OK

已有的代码

  • sysinfotest.c文件部分内容
// 主函数
144 int
145 main(int argc, char *argv[])
146 {
147   printf("sysinfotest: start\n");
148   testcall();
149   testmem();
150   testproc();
151   printf("sysinfotest: OK\n");
152   exit(0);
153 }

//testcall()
 78 void
 79 testcall() {
 80   struct sysinfo info;
 81
 82   if (sysinfo(&info) < 0) {
 83     printf("FAIL: sysinfo failed\n");
 84     exit(1);
 85   }
 86
 87   if (sysinfo((struct sysinfo *) 0xeaeb0b5b00002f5e) !=  0xffffffffffffffff) {
 88     printf("FAIL: sysinfo succeeded with bad argument\n");
 89     exit(1);
 90   }
 91 }

此文件主要处理struct sysinfo结构体记录的信息,sysinfo的信息由内核进行记录,因此要进行系统调用操作,将sysinfo信息复制出来

修改部分

  • kernel文件中,官方提供了sysinfo.h,未提供sysinfo.c,需要自行编写。
//sysinfo.h
1 struct sysinfo {
2   uint64 freemem;   // amount of free memory (bytes)
3   uint64 nproc;     // number of process
4 };

sysinfo.c需要完成将运行中的系统信息写入sysinfo结构体中,最后还需传递到用户态。

  • kernel/kalloc.c中添加一个函数用以收集剩余内存
    • kmem存放了空内存的链表头
    • 遍历空链表统计空余内存
// lab2-3 收集空余的内存
uint64
freemem(void){
  struct run *r;
  uint64 free = 0;

  // 加锁,确保线程安全
  acquire(&kmem.lock);
  // 获取空闲链表头
  r = kmem.freelist;
  // 计算空闲内存(遍历计算)
  while(r){
    free += PGSIZE;
    r = r->next;
  }
  // 释放锁
  release(&kmem.lock);
  // 结果返回
  return free;
}
  • kernel/proc.c中添加函数用以收集进程数量。
    • proc结构体中的state记录了进程的状态信息
// lab2-3 计算进程数量
uint64
nproc(void){
   // 通过遍历proc结构体实现
   int num = 0;
   struct proc* p;
   // p->lock must be held when using these:
   for( p = proc; p < &proc[NPROC]; p++){
      acquire(&p->lock);
      if(p->state != UNUSED ){ // 非未被使用
        num++;
      }
      release(&p->lock);
   }
   return num;
}
  • kernel/defs.h修改
    • 要将上述定义的两个函数添加进defs.h中,defs.h 声明了内核函数
struct sysinfo;
uint64   freemem(void);
uint64   nproc(void);
  • 添加kernel/sysinfo.c文件
    • 用于收集系统信息并传递到用户态
 #include "types.h"
#include "riscv.h"
#include "defs.h"
#include "param.h"
#include "memlayout.h"
#include "spinlock.h"
#include "proc.h"
#include "sysinfo.h"

uint64
sys_sysinfo(void)
{
    struct proc *p = myproc();
    struct sysinfo info;
    uint64 addr; // 用户空间缓冲区
    
    // 获取缓冲区地址
    argaddr(0, &addr);

    
    // 读取状态
    info.freemem = freemem();   // 剩余内存
    info.nproc = nproc();  // 进程数量

    // 将struct sysinfo拷贝至用户态
    if(copyout(p->pagetable, addr, (char*)&info, sizeof(info)) < 0){
         return -1;     
    }
    return 0;
}

  • kernel/syscall.h中添加系统调用号
#define SYS_sysinfo 23
  • kernel/syscall.c注册系统调用
extern uint64 sys_sysinfo(void);
[SYS_sysinfo]  sys_sysinfo,
  • user/user.h增加函数声明
int sysinfo(struct sysinfo *);
  • user/usys.pl增加系统调用入口
    • usys.pl编译后产生usys.S文件,该文件记录了内核函数的入口
entry("sysinfo");
  • Makefile在相应位置添加链接和编译内容
//链接
$K/sysinfo.o\
//编译
$U/_sysinfotest\

你可能感兴趣的:(MIT6.828lab,unix,C,MIT6.828)