MIT 6.828 System calls
asm volatile 内嵌汇编指令语法
System call tracing
增加一个trace系统调用,用户在其他命令前输入trace后,跟踪记录命令使用的相关系统调用(mask指示要跟踪哪些)
$ trace mask command [args]
步骤
1、在Makefile中增加 $U/_trace 到UPROGS,用于编译用户程序user/trace.c
2、在user/user.h中增加trace系统调用的原型
int trace(int);
3、在user/usys.pl中增加trace的汇编指令生成entry
entry("trace");
4、在kernel/syscall.h中增加trace系统调用的编号
#define SYS_sysinfo 23
5、在kernel/proc.h中的proc结构体定义新成员tracemask,保存mask
// Per-process state
struct proc {
struct spinlock lock;
// p->lock must be held when using these:
enum procstate state; // Process state
void *chan; // If non-zero, sleeping on chan
int killed; // If non-zero, have been killed
int xstate; // Exit status to be returned to parent's wait
int pid; // Process ID
// wait_lock must be held when using this:
struct proc *parent; // Parent process
// these are private to the process, so p->lock need not be held.
uint64 kstack; // Virtual address of kernel stack
uint64 sz; // Size of process memory (bytes)
pagetable_t pagetable; // User page table
struct trapframe *trapframe; // data page for trampoline.S
struct context context; // swtch() here to run process
struct file *ofile[NOFILE]; // Open files
struct inode *cwd; // Current directory
char name[16]; // Process name (debugging)
int tracemask; // For system call lab, remember the trace() argument
};
6、在kernel/proc.c中的fork()函数增加复制父进程的mask到子进程,注意要在加锁的时候
7、在kernel/sysproc.c中定义sys_trace函数,实际处理系统调用
uint64
sys_trace(void) {
int mask;
if (argint(0, &mask) < 0) { // 从trap frame中获取用户的参数
return -1;
}
myproc()->tracemask = mask;
return 0;
}
8、在kernel/syscall.c中增加此系统调用到system call table中,用来映射系统调用序号SYS_trace到sys_trace函数
Sysinfo
步骤1、2、3、4、8与上相同
在kernel/sysproc.c中实现sys_sysinfo函数时,需要参考kernel/sysfile.c和kernel/file.c中对用户空间地址的访问(写,copyout()函数)
uint64
sys_sysinfo(void) {
struct proc *p = myproc();
uint64 infoaddr; // address of the user argument
if (argaddr(0, &infoaddr) < 0) {
return -1;
}
struct sysinfo info;
info.freemem = freespaces();
info.nproc = procnum();
if(copyout(p->pagetable, infoaddr, (char *)&info, sizeof(info)) < 0)
return -1;
return 0;
}
在kernel/kalloc.c中实现获取空闲空间大小的函数
// Returns the free space size of bytes
int
freespaces(void) {
struct run *r;
int freenum = 0;
acquire(&kmem.lock);
r = kmem.freelist;
while (r) {
freenum++;
r = r->next;
}
release(&kmem.lock);
return freenum * PGSIZE;
}
在kernel/proc.c中实现获取正在使用的进程的数目的函数
// Returns the number of processes whose state is not UNUSED
int procnum(void) {
struct proc* p;
int nums = 0;
for (p = proc; p < &proc[NPROC]; p++) {
if (p->state != UNUSED) {
nums++;
}
}
return nums;
}
在kernel/defs.h中增加上面两个函数的声明
完成实现kernel/sysproc.c中的sys_sysinfo