Lab System calls
物理资源抽象设计(文件系统管理,内存使用,CPU切换,管道交互);指令执行的三种状态(M,S,U),系统调用;宏内核和微内核;进程机制(S/U mode,地址空间,时间片),进程目的(增强隔离性),进程的地址空间和状态项,进程的设计思想;xv6的启动概述;安全相关。
学习系统调用的原理和实现。
Lab准备
calling convention
系统调用的过程和系统调用的参数
Code: Calling system calls和Code: System call arguments
System call tracing
实现一个系统调用,能打印指定的系统调用的信息。
通过接收参数mask,确定指定的系统调用,在系统调用将返回时,打印出它的信息(进程id,系统调用名称,返回值)。子进程继承这个mask,不影响其他进程。
在struct proc
中加入int tracemask
,用于确定需要trace哪些系统调用。在allocproc
和freeproc
中对这个属性进行初始化和清除。
在syscall
(kernel/syscall.c)中加入实现
if ((p->tracemask & (1 << num)) != 0) {
printf("%d: syscall %s -> %d\n", p->pid, syscallnames[num-1], p->trapframe->a0);
}
在(kernel/sysproc.c)中实现sys_trace
。
// Set mask that specify which system calls to trace.
uint64
sys_trace(void)
{
int tracemask;
if(argint(0, &tracemask) < 0)
return -1;
myproc()->tracemask = tracemask;
return 0;
}
其余配置参照hints修改。
Sysinfo
实现一个系统调用:收集xv6的空闲内存大小和进程数量,并将值返回给用户空间。
在(kernel/sysproc.c)中完成sysinfo系统调用的内核实现sys_sysinfo
。
// Get the number of bytes of free memory,
// and the number of processes whose state is not UNUSED.
uint64
sys_sysinfo(void)
{
uint64 uinfop; // user pointer to struct sysinfo
if(argaddr(0, &uinfop) < 0)
return -1;
return setsysinfo(uinfop);
}
在(kernel/proc.c)完成setsysinfo
和procnum
。分别实现将sysinfo信息传给用户空间和统计进程数量。
// collect the nunmber of processes.
// Return the number of processes whose state is not UNUSED.
uint64
procnum(void)
{
struct proc *p;
uint64 nproc = 0;
for (p = proc; p < &proc[NPROC]; p++) {
acquire(&p->lock);
if (p->state != UNUSED) {
nproc++;
}
release(&p->lock);
}
return nproc;
}
// Set struct sysinfo and copy back to user space.
int
setsysinfo(uint64 addr)
{
struct proc *p = myproc();
struct sysinfo info;
info.freemem = kremainsize();
info.nproc = procnum();
if(copyout(p->pagetable, addr, (char *)&info, sizeof(info)) < 0)
return -1;
return 0;
}
在(kernel/kalloc.c)完成kremainsize
,实现对空闲内存的统计。
// collect the amount of free memory.
// Returns the number of bytes of free memory.
uint64
kremainsize(void)
{
struct run *r;
uint64 freepg = 0;
acquire(&kmem.lock);
r = kmem.freelist;
while (r) {
freepg++;
r = r->next;
}
release(&kmem.lock);
return freepg << 12;
}