Lab2 熟悉一些系统调用,这个实验有一些小坑 😤
实验准备
运行Lab: System calls (mit.edu)上的命令
即可得到该实验的实验环境了。
我们所需要做的就是跟着题目与 Hint
一步一步完成即可。
但在这之前,需要检查你有没有把官网上橙色的部分做完。
System call tracing
要求实现一个跟踪命令的系统调用,在之后或许可以使用这个系统调用来 debug(bushi。
官方的文档已经把要求说的很清楚了,接下来我们跟着 Hint
一步一步做。
- 在
Makefile
中添加$U/_trace$
。 - 运行
make qemu
会发现编译错误,这是因为trace.c
的很多定义都不存在,我们需要去添加定义。- 在
user/user.h
中添加int trace(int);
- 在
usys.pl
中添加entry("trace")
- 在
kernel/syscall.h
中添加#define SYS_trace 22
- 在
kernel/syscall.c
中syscalls
映射表中添加[SYS_trace] sys_trace
,并且添加函数声明extern uint64 sys_trace(void);
- 在
- 在
kernel/proc.h
的proc
中添加成员变量mask
- 在
kernel/sysproc.c
中添加sys_trace
函数的实现 - 修改
kernel/proc.c
中的fork
函数 - 修改
kernel/syscall.c
中的syscall
函数
当我们完成 1,2 步后,我们运行 make qemu
可以发现已经能通过编译了,这是因为我们已经在用户层注册了系统调用 trace
,但当我们运行 trace 32 grep hello README
时会发现调用失败。
因为我们没有在内核层实现 trace
的具体实现,使得用户层无法传递到内核层。
于是,我们在 kernel/sysproc.c
中添加 sys_trace
:
然后根据文档说明,修改 fork
函数与 syscall
函数:
Sysinfo
实现一个 sysinfo
的系统调用,测试的代码已经写好放在 sysinfotest
中。sysinfo
需要打印出可用的内存空间与当前状态不是 UNUSED
的进程数量。
跟随 Hint
一步一步完成。在用户层注册的部分与 trace
部分相同,在此略过。
我们需要在 kernel/sysproc.c
中实现 sys_sysinfo
函数,要求是需要使用 copyout
函数将 struct sysinfo
从内核层传递到用户层。函数的用法可以参照filestat()
(kernel/file.c
)。
需要注意的是,我们还需要添加一行 #include "sysinfo.h"
把 struct sysinfo
链接进来。
然后,我们在 kernel/kalloc.c
中添加 freemem()
以计算空闲空间,在 kernel/proc.c
中添加 nproc()
以计算状态不为 UNUSED
的进程数量。
函数的写法都可以参照同文件下其他函数的写法。
以为这样就可以了吗?
不,现在make qemu
的话,会报错,意思是 freemem()
与 nproc()
函数都未声明。大冤种对比头文件对比了半天发现,我们除了在 sysproc.c
里添加函数外,其他新添加的函数都应该在 defs.h
里面声明(能不能再Hint
里面写一下啊 😒)
添加完后,就会发现编译可以通过了。
最终成绩
做完还是记得 git add . && git commit -m "finish"
更新
做完这个实验其实还是会云里雾里的,因为完全是按照 Hint
很顺畅做下来的,没有什么思考。
我思考了一下还是把这部分放上来,防止之后出现相似的情况。
这个实验其实是想告诉你,xv6
系统乃至其他所有操作系统,究竟是怎么实现系统调用的,为什么你要修改那么多文件等等,但这些如果做完没有思考的话,这个实验等于没做。
由于我在做这个实验前已经写过关于 MINIX
关于添加 chrt
系统调用的实验了(虽然那个也是跟着文档一步一步做的),在做完这个实验后疑惑更深,于是查阅了文档,大概知道了系统调用的过程:
至于为什么需要这么复杂,而不是直接调用函数。
或许认真看一遍 xv6
教材的第一章,这个问题就能迎刃而解。