国外门户网站设计,网站APP推广,网络营销策划书300字,无限流量网站建设系列文章目录
MIT 6.s081 实验解析——labs1 MIT 6.s081 实验解析——labs2 文章目录 系列文章目录测试判断流程System call tracingsysinfo 测试判断流程
完成代码后将.c文…系列文章目录
MIT 6.s081 实验解析——labs1 MIT 6.s081 实验解析——labs2 文章目录 系列文章目录测试判断流程System call tracingsysinfo 测试判断流程
完成代码后将.c文件放入user文件夹中在makefile文件的UPROGS处添加要测试的文件如要添加的是sleep.c则写为_sleep。 重新编译xv6
make qemu退出qemu在文件夹下输入
./grade-lab-util 文件名//以sleep为例
./grade-lab-util sleepSystem call tracing trace 32 grep hello README以上述指令来说这个实验想要实现的效果是跟踪grep hello README过程中所有的系统调用其中32为掩码是要跟踪的系统调用种类将32变为2进制根据下图在要跟踪的系统调用位置置1。 所以先更改kernel/proc.h的进程结构体新增掩码 struct proc {...int mask;};为了实现进程间传递参数需添加对mask的拷贝在kernel/proc.c的fork定义中 intfork(void){...// Cause fork to return 0 in the child.np-trapframe-a0 0;np-mask p-mask;...}接下来就是要去完成系统调用 trace 的函数定义在该系统调用会接收用户态传递的参数并将其赋值给mask我们将定义写在kernel/sysproc.c中: uint64sys_trace(void){int n;argint(0,n);//接收参数myproc()-mask n;//赋给maskreturn 0;}为了在syscall中能调用sys_trace我们需要将其函数入口地址存入数组static uint64 (*syscalls[])(void)中在其末尾加入[SYS_trace] sys_trace,即可。 最后我们要在syscall调用完系统调用后通过本进程的mask来确认这个系统调用是不是被追踪的若是则输出相关信息为了方便信息输出我们为其定义一个字符串数组修改的文件为kernel/syscall.c: char *str[]{[SYS_fork] syscall fork,[SYS_exit] syscall exit,[SYS_wait] syscall wait,[SYS_pipe] syscall pipe,[SYS_read] syscall read,[SYS_kill] syscall kill,[SYS_exec] syscall exec,[SYS_fstat] syscall fstat,[SYS_chdir] syscall chdir,[SYS_dup] syscall dup,[SYS_getpid] syscall getpid,[SYS_sbrk] syscall sbrk,[SYS_sleep] syscall sleep,[SYS_uptime] syscall uptime,[SYS_open] syscall open,[SYS_write] syscall write,[SYS_mknod] syscall mknod,[SYS_unlink] syscall unlink,[SYS_link] syscall link,[SYS_mkdir] syscall mkdir,[SYS_close] syscall close,[SYS_trace] syscall trace,};voidsyscall(void){int num;struct proc *p myproc();num p-trapframe-a7; //系统调用号if(num 0 num NELEM(syscalls) syscalls[num]) {// Use num to lookup the system call function for num, call it,// and store its return value in p-trapframe-a0p-trapframe-a0 syscalls[num](); //系统调用的返回值if((p-mask num) 1) //若该系统调用被跟踪printf(%d: %s - %d\n,p-pid,str[num],p-trapframe-a0);//输出信息} else {printf(%d %s: unknown sys call %d\n,p-pid, p-name, num);p-trapframe-a0 -1;}}描述一下整个系统调用的流程核心点就在于可以通过usys.pl文件里对系统调用的定义使得可以在用户空间调用系统调用。 在用户空间的trace.c定义了trace调用然后通过ECALL指令触发向内核态的切换将对应的系统调用号和参数存入寄存器切换至内核态之后由syscall函数对调用进行响应然后调用对应的系统调用。处理完成之后将结果返还给用户空间再切换回用户态完成一次系统调用。
sysinfo
整体流程和trace差不多获取非unused的进程数核心就是遍历进程结构体数组proc并判断其元素的state。 uint64 get_used_proc(){struct proc *p;uint64 n 0;for(p proc; p proc[NPROC]; p) {if(p-state ! UNUSED) n;}return n;}获取空闲内存通过查看文件kernel/kalloc.c可知每个物理内存页的单位是PGSIZE4096字节, 以一个单链表的形式管理空闲内存页我们只需遍历该单链表获取空闲页数每页计一个PGSIZE即可。 uint64 get_free_memory(){uint64 n0;struct run* r kmem.freelist;while(r){rr-next;n PGSIZE;}return n;}将这些信息填入sysinfo结构体然后返还给用户空间。 uint64 sys_sysinfo(){uint64 st;argaddr(0, st);//获取从用户空间传入的指针。struct sysinfo p;//将信息存在结构体中p.nproc get_used_proc();p.freemem get_free_memory();if(copyout(myproc()-pagetable, st, (char *)p, sizeof(p)) 0)//拷贝回用户空间return -1;return 0;}