我们来一步步为 xv6 添加一个新的系统调用 freemem(),它返回当前系统中可用的空闲内存页数(单位:字节)。


🧩 Step 1:理解原理

xv6 使用 kalloc.c 中的 freelist 链表维护空闲内存页,我们可以通过遍历 freelist 来统计可用页数。


🛠 Step 2:修改 xv6 源码(假设你在 xv6-labs 或 MIT 的 xv6-public 项目中)

✅ 2.1 编辑 syscall.h:添加系统调用号

// syscall.h
#define SYS_freemem  23   // 选择一个未用的编号(根据你前面系统调用数量调整)

✅ 2.2 编辑 syscall.c:添加系统调用名称

extern uint64 sys_freemem(void);

static uint64 (*syscalls[])(void) = {
  ...
  [SYS_freemem]   sys_freemem,
};

✅ 2.3 编辑 usys.S:添加用户态声明

// usys.S
SYSCALL(freemem)

因为不是直接编写 usys. S 的, 是通过 usys.pl 脚本编写的, 所以我们在 usys.pl 里编写即可


✅ 2.4 编辑 user.h:添加用户头文件函数声明

// user.h
int freemem(void);

✅ 2.5 添加内核处理函数:sysproc.c

// sysproc.c
extern struct run *freelist;  // 定义于 kalloc.c 中

uint64
sys_freemem(void)
{
  struct run *r;
  int freepages = 0;

  acquire(&kmem.lock);   // 锁住空闲页链表
  for(r = kmem.freelist; r; r = r->next)
    freepages++;
  release(&kmem.lock);

  return (uint64)freepages * PGSIZE;  // 返回单位为字节
}

如果你没有看到 kmem.freelist,可以检查 kalloc.c,确保 kmem

struct 
{
	struct spinlock lock;
	struct run \*freelist;
}

的类型。


🧪 Step 3:编写测试程序 freememtest.c

// freememtest.c
#include "kernel/types.h"
#include "user.h"

int
main(void)
{
  int mem = freemem();
  printf("Free memory: %d bytes\n", mem);
  exit(0);
}

🧱 Step 4:把测试程序加进 Makefile 和 UPROGS

Makefile 中添加:

UPROGS += _freememtest

🚀 Step 5:编译并运行

$ make qemu
$ freememtest
Free memory: 123456 bytes

如果你卡在某一步或想做进一步扩展,比如显示为 KB / MB 单位、在 shell 命令中集成、定时打印、创建 /proc/meminfo 类似的文件接口,我也可以一步步帮你扩展!