根据文档的指引, 在 user/user.h
, user/usys.pl
, kernel/syscall.h
中添加对应的代码, 分别为:
user/user.h
:
int trace(int);
user/usys.pl
:
entry("trace");
kernel/syscall.h
:
#define SYS_trace 22
而后在 kernel/sysproc.h
中添加 uint sys_trace(void)
的实现, 在实现过程中, 尽管参数被存在结构体 proc
的成员 a1 - a6
中, 然而在 kernel/syscall.c
中已经提供了 int argint(int n, int *ip)
以供使用, 故直接调用即可得到系统调用的参数.
得到参数后再解决如何记录待 “trace
” 的调用的变量 mask
的问题, 该问题可以通过在 kernel/proc.h
中的结构体 proc
中添加成员变量 tracemask
中解决. 同时为了使得 fork()
得到的子进程也具有同样的 tracemask
, 在 kernel/proc.c
的 fork()
函数中添加以下语句:
np->tracemask = p->tracemask;
解决上述问题后, sys_trace()
的实现便呼之欲出了, 直接获取参数后将其保存至结构体对应的成员变量即可:
uint64
sys_trace(void)
{
struct proc *p = myproc();
if (argint(0, &(p->tracemask)))
return -1;
return 0;
}
然后再实现最后的如何 trace
的问题, 根据文档, 在 kernel/syscall.c
中修改 syscall()
的实现, 在调用前将该系统调用对应的数字以及 tracemask
通过左移和按位与运算做判断, 如果是需要 trace
的系统调用则输出即可. 为了便捷地打印字符串, 可效仿 syscalls[]
数组创建一个类似的数组保存调用名.
修改后的 kernel/syscall.c
代码片段如下:
extern uint64 sys_trace(void);
static uint64 (*syscalls[])(void) = {
[SYS_fork] sys_fork,
[SYS_exit] sys_exit,
[SYS_wait] sys_wait,
[SYS_pipe] sys_pipe,
[SYS_read] sys_read,
[SYS_kill] sys_kill,
[SYS_exec] sys_exec,
[SYS_fstat] sys_fstat,
[SYS_chdir] sys_chdir,
[SYS_dup] sys_dup,
[SYS_getpid] sys_getpid,
[SYS_sbrk] sys_sbrk,
[SYS_sleep] sys_sleep,
[SYS_uptime] sys_uptime,
[SYS_open] sys_open,
[SYS_write] sys_write,
[SYS_mknod] sys_mknod,
[SYS_unlink] sys_unlink,
[SYS_link] sys_link,
[SYS_mkdir] sys_mkdir,
[SYS_close] sys_close,
[SYS_trace] sys_trace,
[SYS_sysinfo] sys_sysinfo
};
char *syscallsnames[] = {
[0] "",
[SYS_fork] "fork",
[SYS_exit] "exit",
[SYS_wait] "wait",
[SYS_pipe] "pipe",
[SYS_read] "read",
[SYS_kill] "kill",
[SYS_exec] "exec",
[SYS_fstat] "fstat",
[SYS_chdir] "chdir",
[SYS_dup] "dup",
[SYS_getpid] "getpid",
[SYS_sbrk] "sbrk",
[SYS_sleep] "sleep",
[SYS_uptime] "uptime",
[SYS_open] "open",
[SYS_write] "write",
[SYS_mknod] "mknod",
[SYS_unlink] "unlink",
[SYS_link] "link",
[SYS_mkdir] "mkdir",
[SYS_close] "close",
[SYS_trace] "trace",
[SYS_sysinfo] "sysinfo"
};
void
syscall(void)
{
int num;
struct proc *p = myproc();
num = p->trapframe->a7;
if(num > 0 && num < NELEM(syscalls) && syscalls[num]) {
p->trapframe->a0 = syscalls[num]();
if (p->tracemask & (1 << num))
printf("%d: syscall %s -> %d\\n", p->pid, syscallsnames[num], p->trapframe->a0);
} else {
printf("%d %s: unknown sys call %d\\n",
p->pid, p->name, num);
p->trapframe->a0 = -1;
}
}
首先按照与 trace
相同的步骤在对应的文件中添加代码: