system call tracing
要求:
在本作业中,您将添加一个系统调用跟踪特性,这可能会在调试以后的实验时帮助您。 您将创建一个新的跟踪系统调用来控制跟踪。 它应该接受一个参数,一个整数“mask”,其位指定要跟踪哪个系统调用。 例如,要跟踪fork系统调用,程序调用trace(1 << SYS_fork),其中SYS_fork是来自kernel/syscall.h的一个系统调用号。 如果在掩码中设置了系统调用的编号,则必须修改xv6内核,以便在每个系统调用即将返回时打印一行。 这一行应该包含进程id、系统调用的名称和返回值; 您不需要打印系统调用参数。 跟踪系统调用应该对调用它的进程及其随后分叉的任何子进程启用跟踪,但不应影响其他进程。
提示:
在Makefile中添加$U/_trace到UPROGS
运行make qemu,您将看到编译器无法编译user/trace.c,因为用于系统调用的用户空间存根还不存在:将系统调用的原型添加到user/user.h,将存根添加到user/usys.pl,将系统调用号添加到kernel/syscall.h。 Makefile调用perl脚本user/usys.pl,生成user/usys.pl。 S,实际的系统调用存根,它们使用RISC-V调用指令转换到内核。 修复编译问题后,运行trace 32 grep hello README; 它将失败,因为您还没有在内核中实现系统调用。
在kernel/sysproc.c中添加一个sys_trace()函数,该函数通过在proc结构中的新变量中记住它的参数来实现新的系统调用(参见kernel/proc.h)。 从用户空间检索系统调用参数的函数在kernel/syscall.c中,您可以在kernel/sysproc.c中看到它们的使用示例。
修改fork()(参见kernel/proc.c)将跟踪掩码从父进程复制到子进程。
修改kernel/syscall.c中的syscall()函数以打印跟踪输出。 您将需要添加一个要索引到的系统调用名称数组。
uint64
sys_trace(void)
{
int n;
if (argint(0, &n) < 0) {//argint 获取系统调用参数
return -1;
}
struct proc* p = myproc();
char* mask = p->mask;
for (int i = 0; i < 23 && n>0; i++) {
if (n % 2 != 0) {
mask[i] = '1';
}
else {
mask[i] = '0';
}
n>>=1;
}
return 0;
}
结果:
提交:
./grade-lab-syscall trace
sysinfo
要求:
在这个作业中,你将添加一个系统调用sysinfo,它收集关于正在运行的系统的信息。系统调用有一个参数:一个指向结构体sysinfo的指针(参见kernel/sysinfo.h)。内核应该填充这个结构体的字段:freemem字段应该设置为空闲内存的字节数,nproc字段应该设置为状态不是UNUSED的进程的数量。我们提供了一个测试程序sysinfotest;如果输出“sysinfotest: OK”,则通过该赋值。
提示:
在Makefile中添加$U/_sysinfotest到UPROGS
运行make qemu;sysinfotest.c编译失败。按照前面任务的步骤添加系统调用sysinfo。要在user/user.h中声明sysinfo()的原型,你需要预先声明struct sysinfo的存在:
struct sysinfo;
Int sysinfo(struct sysinfo *);
修复编译问题后,运行sysinfotest;它将失败,因为您还没有在内核中实现系统调用。
Sysinfo需要复制一个结构体Sysinfo回用户空间;请参阅sys_fstat() (kernel/sysfile.c)和filestat() (kernel/file.c)以了解如何使用copyout()来实现这一点。
要收集空闲内存,可以在kernel/kalloc.c中添加一个函数
为了收集进程的数量,在kernel/proc.c中添加一个函数
//kernel kalloc.c
int
freemem_size(void)
{
struct run* r = kmem.freelist;
int num = 0;
while (r) {
num++;
r = r->next;
}
return num * PGSIZE;
}
//kernel proc.c
int
proc_num(void) {
struct proc* p;
int num = 0;
for (p = proc; p < &proc[NPROC]; p++) {
if (p->state != UNUSED) {
num++;
}
}
return num;
}
//kernel sysproc.c
uint64
sys_sysinfo(void){
struct sysinfo info;
uint64 addr;
struct proc* p = myproc();
if(argaddr(0, &addr) < 0)
return -1;
info.freemem = freemem_size();
info.nproc = proc_num();
if(copyout(p->pagetable, addr, (char *)&info, sizeof(info)) < 0)
return -1;
return 0;
}
提交:
./grade-lab-syscall sysinfo