首先切换分支
git fetch git checkout syscall
system call trace
添加一个系统调用跟踪功能
例如跟踪fork系统调用,可以使用trace 1<< SYS_fork ,其中SYS_fork是kernel/syscall.h中的系统调用编号
例如下列例子:
$ trace 32 grep hello README
3: syscall read -> 1023
3: syscall read -> 966
3: syscall read -> 70
3: syscall read -> 0
$
$ trace 2147483647 grep hello README
4: syscall trace -> 0
4: syscall exec -> 3
4: syscall open -> 3
4: syscall read -> 1023
4: syscall read -> 966
4: syscall read -> 70
4: syscall read -> 0
4: syscall close -> 0
例如第一个是32,也是1 << SYS_read
1.在Makefile中的UPROGS中添加$U/_trace
2.将系统调用原型添加到user/user.h中
3.将存根添加到user/usys.pl,这段perl调用makefile文件调用,生成实际的系统调用存根user/usys.S
4.将系统调用编号添加到kernel/syscall.h中
5.在kernel/proc.h中proc结构体中添加一个数据字段用来保存trace的参数
struct proc{
……
int trace_mask;
}
6.在kernel/sysproc.c中sys_trace()保存第一个参数,0表示读取输入的第一个参数
7.在syscall.c中的syscalls_name[]定义一些系统调用用于打印信息
8.接下来实现trace,其实就是在syscall函数中做埋点,将拿到的系统调用编号与此时的掩码位运算,如果为1那么就进行打印,最后输出的a0是返回值
在这里补充一下:
p
是指向当前进程结构体 (struct proc
) 的指针
trapframe 是 struct proc 中的一个字段,指向 struct trapframe。trapframe 保存了进程在发生中断、异常或系统调用时的寄存器状态。
a7 是 struct trapframe 中的一个字段,表示寄存器 a7。在 RISC-V 架构中,a7 寄存器通常用于存储系统调用编号。
测试输出一下:
trace_mask是一个位图,每个进程执行系统调用时,会获取当前系统调用号,通过移位获得对应的位数,再通过想与查看是否被跟踪再输出相应打点信息。
Sysinfo
这个实验需要添加一个系统调用sysinfo用于收集正在运行的系统的信息。
在user/sysinfotest.c中已经提供了相关的sinfo程序让用户调用
sysinfo结构体如下 kernel/sysinfo.h
1.在Makefile的UPROGS中添加$U/_sysinfotest
2.在user/user.h头文件中声明struct sysinfo的存在同时声明sysinfo()的原型
3.在user/usys.pl中添加存根
entry("sysinfo");
4.将系统调用编号添加到kernel/syscall.h中
5.在kernel/kalloc.c中添加一个函数用于获取空闲内存量
事实上xv6空闲内存管理方式时链表法,每次需要分配将链表头部页先分出去,每次需要回收就采用头插法放回来
编写获取空闲内存量的函数freebytes
上述内存分配方式通过kalloc函数可以验证:
6.在kernel/proc.c中添加一个函数获取进程数
7.在内核头文件kernel/defs.h中添加函数声明
void freebytes(uint64 *dst); void procnum(uint64 *dst);
8.在kernel/sysproc.c文件中实现sys_sysinfo,记得加上sysinfo结构体定义所在的头文件
9.最后在kernel/syscall.c中补充sysinfo系统调用
测试一下
sudo ./grade-lab-syscall sysinfo