MIT6.s081 lab System calls
lab System calls
0、time
4 hours
1、trace
// 1.在user/user.h中加上trace函数定义
int trace(int);
// 2.在user/usys.pl中加上trace的entry脚本
entry("trace");
// 3.在kernel/proc.h的struct proc定义中加上teacemask标志
uint64 tracemask; // bit mask for tracing
// 4.kernel/proc.c中有两个函数需要改动
1.
static struct proc*
allocproc(void)
{
...
//初始化tracemask(我们要添加的语句)
p->tracemask = 0;
return p;
}
allocproc函数的作用是找一个没使用过的proc,所以在一个进程创建时,此函数一定会执行,我们的目的就是在创建进程时就把tracemask初始化为0
2.
int
fork(void)
{
...
// Allocate process.
if((np = allocproc()) == 0){
return -1;
}
//继承父进程的trace mask(我们要添加的语句)
np->tracemask = p->tracemask;
// Copy user memory from parent to child.
if(uvmcopy(p->pagetable, np->pagetable, p->sz) < 0){
freeproc(np);
release(&np->lock);
return -1;
}
...
}
// 5.实现kernel/sysproc.c中的sys_trace函数
uint64
sys_trace(void) {
int trace_sys_mask;
if (argint(0, &trace_sys_mask) < 0)//从a0寄存器获取参数
return -1;
myproc()->tracemask |= trace_sys_mask;
return 0;
}
// 6.修改kernel/syscall.h,syscall.c的某些定义
1.
#define SYS_trace 22
2.
static uint64 (*syscalls[])(void) = {
...
[SYS_trace] sys_trace,//添加这行
};
//添加下面这个字符串数组
static char *sysnames[] = {
"",
"fork",
"exit",
"wait",
"pipe",
"read",
"kill",
"exec",
"fstat",
"chdir",
"dup",
"getpid",
"sbrk",
"sleep",
"uptime",
"open",
"write",
"mknod",
"unlink",
"link",
"mkdir",
"close",
"trace",
"sysinfo"
};
// 7.修改kernel/syscall.函数syscall
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]();//返回值存在a0寄存器中
if (p->tracemask & (1 << num))
printf("%d: syscall %s -> %d\n", p->pid, sysnames[num], p->trapframe->a0);
} else {
printf("%d %s: unknown sys call %d\n",
p->pid, p->name, num);
p->trapframe->a0 = -1;
}
}
//执行流
user/trace.c -> trace()
user/usys.pl -> entry
kernel/syscall.c -> syscall()
syscall() -> kernel/sysproc.c:sys_trace()
2、sysinfo
1.获取空闲内存大小
uint64 kfreemem(void) {
struct run *r;
uint64 freesize = 0;
acquire(&kmem.lock);
r = kmem.freelist;
while (r) {
freesize += PGSIZE;
r = r->next;
}
release(&kmem.lock);
return freesize;
}
2.获取正在使用的进程数
uint64 kfreemem(void) {
struct run *r;
uint64 freesize = 0;
acquire(&kmem.lock);
r = kmem.freelist;
while (r) {
freesize += PGSIZE;
r = r->next;
}
release(&kmem.lock);
return freesize;
}
3.sys_sysinfo
uint64
sys_sysinfo(void) {
struct proc *my_proc = myproc();
uint64 p;
if (argaddr(0, &p) < 0)//读取a0寄存器内容放到p中:此时存的是sysinfo结构体地址
return -1;
struct sysinfo s;
s.freemem = kfreemem();
s.nproc = procnum();
if ((copyout(my_proc->pagetable, p, (char *)&s, sizeof(s))) < 0)
return -1;
return 0;
}
3、总结
必须将代码的执行流理顺
合集:
mit6.s081
【推荐】国内首个AI IDE,深度理解中文开发场景,立即下载体验Trae
【推荐】编程新体验,更懂你的AI,立即体验豆包MarsCode编程助手
【推荐】抖音旗下AI助手豆包,你的智能百科全书,全免费不限次数
【推荐】轻量又高性能的 SSH 工具 IShell:AI 加持,快人一步
· 无需6万激活码!GitHub神秘组织3小时极速复刻Manus,手把手教你使用OpenManus搭建本
· Manus爆火,是硬核还是营销?
· 终于写完轮子一部分:tcp代理 了,记录一下
· 别再用vector<bool>了!Google高级工程师:这可能是STL最大的设计失误
· 单元测试从入门到精通