System calls [os lab2]
system call的相关代码
user-space code: user/user.h
, user/user.pl
kernel-space code: kernel/syscall.h
, kernal/syscall.c
process-related code: kernel/proc.h
, kernel/proc.c
先switch git branch到sycall
git fetch |
1. System call tracing
In this assignment you will add a system call tracing feature that may help you when debugging later labs. You’ll create a new trace
system call that will control tracing. It should take one argument, an integer “mask”, whose bits specify which system calls to trace. For example, to trace the fork system call, a program calls trace(1 << SYS_fork)
, where SYS_fork
is a syscall number from kernel/syscall.h
. You have to modify the xv6 kernel to print out a line when each system call is about to return, if the system call’s number is set in the mask. The line should contain the process id, the name of the system call and the return value; you don’t need to print the system call arguments. The trace
system call should enable tracing for the process that calls it and any children that it subsequently forks, but should not affect other processes.
这个任务会增加一个system call tracing的feature。我们需要创建一个新的system call trace
来控制tracing。他需要接收一个参数,一个整数"mask",代表了需要trace的system calls。
Example:
$ trace 32 grep hello README |
In the first example above, trace invokes grep tracing just the read system call. The 32 is 1<<SYS_read
In the second example, trace runs grep while tracing all system calls; the 2147583647 has all 31 low bits set.
In the third example, the program isn’t traced, so no trace output is printed. In the fourth example, the fork system calls of all the descendants of the forkforkfork
test in usertests
are being traced.
Your solution is correct if your program behaves as shown above (though the process IDs may be different).
Some hints
- Add
$U/_trace
to UPROGS in Makefile
- Run
make qemu
and you will see that the compiler cannot compileuser/trace.c
This is because the user-space stubs for the system call don’t exist yet:
- add a prototype for the system call to
user/user.h
, a stub touser/usys.pl
, a syscall number tokernel/syscall.h
The Makefile invokes the perl script user/usys.pl
, which produces user/usys.S
, the actual system call stubs, which use the RISC-V ecall instruction to transition to the kernel.
将SYS_trace
这个syscall number放入寄存器a7
, 然后ecall
进入kernel mode
.global trace |
Once you fix the compilation issues, run trace 32 grep hello README; it will fail because you haven’t implemented the system call in the kernel yet.
- Add a
sys_trace()
function inkernel/sysproc.c
that implements the new system call by remembering its argument in a new variable in the proc structure (seekernel/proc.h
).
在 kernel/proc.h
中的proc结构体中新增一个mask成员变量。
在 kernle/sysproc.c
中增加 sys_trace
函数。The functions to retrieve system call arguments from user space are in kernel/syscall.c
, and you can see examples of their use in kernel/sysproc.c
.
在 syscall.c
中声明 sys_trace
函数,然后在 syscalls
这个函数指针数组中增加 sys_trace
。
实现sys_trace
函数,首先通过argint
获取mask参数,然后将mask参数赋给proc
uint |
- Modify
fork()
(seekernel/proc.c
) to copy the trace mask from the parent to the child process.
在fork
函数中增加一行copy mask的代码
np->mask = p->mask;//这行是新增的,copy mask |
- Modify the
syscall()
function inkernel/syscall.c
to print the trace output. You will need to add an array of syscall names to index into.
在kernel/syscall.c
中增加一个 syscallnames
这个数组,方便打印系统调用的名字
syscall
的代码修改如下:
如果 (1 << num) & p->mask != 0
说明num属于mask trace的系统调用,按照格式打印系统调用内容: pid, syscall name, return value。注意return value存储在a0
寄存器中
void |
Sysinfo
In this assignment you will add a system call, sysinfo
, that collects information about the running system. The system call takes one argument: a pointer to a struct sysinfo (see kernel/sysinfo.h
). The kernel should fill out the fields of this struct: the freemem field should be set to the number of bytes of free memory, and the nproc field should be set to the number of processes whose state is not UNUSED. We provide a test program sysinfotest
; you pass this assignment if it prints “sysinfotest: OK”.
Some hints
- Add
$U/_sysinfotest
toUPROGS
in Makefile
- Run make qemu;
user/sysinfotest.c
will fail to compile. Add the system callsysinfo
, following the same steps as in the previous assignment. To declare the prototype forsysinfo()
inuser/user.h
you need predeclare the existence of struct sysinfo:
struct sysinfo; |
在 user/user.h
中声明 sysinfo
函数, 在 user/usys.pl
中增加 sysinfo
entry, 在 kernel/syscall.h
中定义 sysinfo
的系统调用号为23
在 kernel/syscall.c
中修改如下三处信息
sysinfo
needs to copy a struct sysinfo back to user space; seesys_fstat()
(kernel/sysfile.c
) andfilestat()
(kernel/file.c
) for examples of how to do that usingcopyout()
. To collect the amount of free memory, add a function tokernel/kalloc.c
。 To collect the number of processes, add a function tokernel/proc.c
其中两个函数 nfree()
, nproc()
函数需要我们自己定义
nfree()
函数用来获取空闲内存的数量,以byte为单位返回。定义在 kernel/kalloc.c
中
nproc()
函数返回非 UNUSED
state的进程数量。定义在 kernel/proc.c
中
nfree()
的实现参考kernel/kalloc.c/kalloc()
的代码,如下
void * |
nproc()
的实现参考kernel/proc.c/procdump()
的代码,如下
for(p = proc; p < &proc[NPROC]; p++){ |
为了使用这两个函数和 sysinfo
这个结构体,还需要在 kernel/defs.h
中声明函数。然后在 kernel/sysproc.c
中 #include "sysinfo.h
引入结构体信息,