MIT 6.828 Homework3:system call
作者:互联网
首先是要在syscall.c.中修改代码,使它能够为每个系统调用都能够输出一部分的跟踪信息,如图:
于是找到syscall.c,这里没有什么特别好的方法,因此就用了简单粗暴的数组了:
static const char*sysname[]={ [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", };
然后加上这么一句即可:
void syscall(void) { int num; struct proc *curproc = myproc(); num = curproc->tf->eax; if(num > 0 && num < NELEM(syscalls) && syscalls[num]) { cprintf("%s -> %d\n", syscall_name[num], syscalls[num]()); } else { cprintf("%d %s: unknown sys call %d\n", curproc->pid, curproc->name, num); curproc->tf->eax = -1; } }
接下来的第二个任务是要添加一个系统调用,这里首先注意到指导书上给出的这个指令:
grep -n uptime *.[chs]
直接在自己的终端打开使用即可:
首先需要创建date.c文件,并且完成main函数的代码:
#include "types.h" #include "user.h" #include "date.h" int main(int argc, char *argv[]) { struct rtcdate r; if (date(&r)) { printf(2, "date failed\n"); exit(); } // your code to print the time in any format you like... printf(1,"%d/%d/%d %d:%d:%d\n",r.year,r.month,r.day,r.hour,r.minute,r.second); exit(); }
rtcdate的结构如下:
struct rtcdate { uint second; uint minute; uint hour; uint day; uint month; uint year; };
date函数取得时间后,对应时间存储在rtcdate中。因此直接简单打印出来即可。注意到date函数是有参数的,因此在打开最后的user.h文件中,定义如下:
int date(struct rtcdate*);
因此接下来的操作是如何实现对应的系统调用的代码:
int sys_date(void){ struct rtcdate*d; if(argptr(0,(void*)&d,sizeof(struct rtcdate))<0) return -1; cmostime(d); return 0; }
这里的问题在于为什么要调用argptr函数。argptr函数:
int argptr(int n, char **pp, int size) { int i; struct proc *curproc = myproc(); if(argint(n, &i) < 0) return -1; if(size < 0 || (uint)i >= curproc->sz || (uint)i+size > curproc->sz) return -1; *pp = (char*)i; return 0; }
涉及到xv6的系统调用机制,简单来理解就是,这个函数是用来抓取系统调用的参数的。换言之,我们在date函数中,有一个结构体参数struct rtcdate,因此这里就可以通过argptr来获得传递进来的参数,然后接下来利用cmostime函数,最终让rtcdate得到时间数据。于是在之后切换回用户态时,此时我们的date.c文件中的main函数即可进行使用。于是我们就完成了这个系统调用的代码工作。
接下来需要注意的是,还要打开usys.s文件,进行对应的添加。然后在makefile对应的UPROGS添加_date即可。
另外,最好把之前进行描述的语句删除掉,否则显示端可能不会显示内容。
之后打开终端,执行make qemu命令,唤醒我们的终端,然后再执行date命令即可完成上述操作。
以及接下来的挑战任务:
dup2函数介绍:
函数原型:int dup2(int oldfd,int newfd);
函数作用:为oldfd指向的文件分配一个新的文件描述符newfd,当newfd指向的文件已被系统使用时,关闭该文件,再进行分配,当newfd=oldfd时,不关闭newfd,分配成功后,oldfd与newfd将指向同一文件。
函数返回值:newfd。
于是问题在于怎么去找到对应的打开的文件表,它在这里:
然后的话构思一下对应的系统调用函数,思路其实特别简单:
很明显oldfd和newfd正好是我们需要的,因此首先是获得这两个参数,并且进行一定的边界测试,测试通过后就可以进行对应的操作了:
int sys_dup2(void){ int oldfd, newfd; if (argint(0, &oldfd) < 0 || argint(1, &newfd) < 0 || oldfd >= NOFILE || newfd >= NOFILE || oldfd < 0 || newfd < 0) { return -1; } struct file* oldfile = myproc()->ofile[oldfd]; struct file* newfile = myproc()->ofile[newfd]; if (!oldfile) return -1; else if (oldfd != newfd) { if (newfile) fileclose(newfd);//关闭对应的文件夹 myproc()->ofile[newfd] = oldfile; filedup(oldfd);//计数+1 } return newfd; }
argint函数,有2个参数,第一个参数代表对应系统调用函数的第几个参数。例如我们将来传递进来的那2个参数分别是oldfd和newfd。oldfd是第一个,于是argint函数中的0代表了读取oldfd。1代表读取newfd。
标签:SYS,date,int,system,sys,oldfd,call,Homework3,newfd 来源: https://www.cnblogs.com/liyucheng0529/p/14551889.html