我们来一步步为 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 类似的文件接口,我也可以一步步帮你扩展!