[OS] Xv6 System Calls
来源:互联网 发布:java中的多态如何理解 编辑:程序博客网 时间:2024/05/22 08:02
Part One: System call tracing
Your first task is to modify the xv6 kernel to print out a line for each system call invocation. It is enough to print the name of the system call and the return value; you don’t need to print the system call arguments.
When you’re done, you should see output like this when booting xv6:
...fork -> 2exec -> 0open -> 3close -> 0$write -> 1 write -> 1
That’s init forking and execing sh, sh making sure only two file descriptors are open, and sh writing the $ prompt. (Note: the output of the shell and the system call trace are intermixed, because the shell uses the write syscall to print its output.)
Hint: modify the syscall() function in syscall.c.
Optional challenge: print the system call arguments.
第一步,我们要跟踪系统调用,并把他们打印在终端上。
首先,我们要看一下 syscall.h
// System call numbers#define SYS_fork 1#define SYS_exit 2#define SYS_wait 3#define SYS_pipe 4#define SYS_read 5#define SYS_kill 6#define SYS_exec 7#define SYS_fstat 8#define SYS_chdir 9#define SYS_dup 10#define SYS_getpid 11#define SYS_sbrk 12#define SYS_sleep 13#define SYS_uptime 14#define SYS_open 15#define SYS_write 16#define SYS_mknod 17#define SYS_unlink 18#define SYS_link 19#define SYS_mkdir 20#define SYS_close 21
这里面定义了系统调用的名称和对应的序号,我们要在终端上显示的就是上面这些对应的名字和编号。
下面,我们要进行文件修改了。
打开文件:syscall.c
在文件前面添加编号和系统调用名称相互对应的数组:
...#include "x86.h"#include "syscall.h"// 以下为添加的内容static char SYS_call_names[][6] = { [SYS_fork] "fork", [SYS_exit] "exit", [SYS_wait] "wait", [SYS_pipe] "pipe", [SYS_read] "read", [SYS_kill] "kill", [SYS_exec] "exec", [SYS_fstat] "fstat", [SYS_chdir] "chdir", [SYS_dup] "dup", [SYS_getpid] "getpid", [SYS_sbrk] "sbrk", [SYS_sleep] "sleep", [SYS_uptime] "uptime", [SYS_open] "open", [SYS_write] "write", [SYS_mknod] "mknod", [SYS_unlink] "unlink", [SYS_link] "link", [SYS_mkdir] "mkdir", [SYS_close] "close"};// 以上为添加的内容// User code makes a system call with INT T_SYSCALL.// System call number in %eax....
然后在函数:syscall
中添加对应的输出命令:
void syscall(void){ int num; struct proc *curproc = myproc(); num = curproc->tf->eax; if (num > 0 && num < NELEM(syscalls) && syscalls[num]) { curproc->tf->eax = syscalls[num]();// 以下为添加的内容// 添加的是下面这一行代码,打印系统调用名称和编号并换行,使用制表符对齐格式 cprintf("\tSYS_call: %s\tid: %d\n", SYS_call_names[num], num);// 以上为添加的内容 } else { cprintf("%d %s: unknown sys call %d\n", curproc->pid, curproc->name, num); curproc->tf->eax = -1; }}
至此,第一部分的代码修改就完成了。
最后,在ubuntu虚拟机中编译运行:
$ make qemu-nox
运行结果如下:
qemu-system-i386 -nographic -drive file=fs.img,index=1,media=disk,format=raw -drive file=xv6.img,index=0,media=disk,format=raw -smp 1 -m 512 -snapshotxv6...cpu0: starting 0sb: size 20000 nblocks 19937 ninodes 200 nlog 30 logstart 2 inodestart 32 bmap start 58 SYS_call: exec id: 7 SYS_call: open id: 15 SYS_call: mknod id: 17 SYS_call: open id: 15 SYS_call: dup id: 10 SYS_call: dup id: 10i SYS_call: write id: 16n SYS_call: write id: 16i SYS_call: write id: 16t SYS_call: write id: 16: SYS_call: write id: 16 SYS_call: write id: 16s SYS_call: write id: 16t SYS_call: write id: 16a SYS_call: write id: 16r SYS_call: write id: 16t SYS_call: write id: 16i SYS_call: write id: 16n SYS_call: write id: 16g SYS_call: write id: 16 SYS_call: write id: 16s SYS_call: write id: 16h SYS_call: write id: 16 SYS_call: write id: 16 SYS_call: fork id: 1 SYS_call: exec id: 7 SYS_call: open id: 15 SYS_call: close id: 21$ SYS_call: write id: 16 SYS_call: write id: 16
Part Two: Date system call
Your second task is to add a new system call to xv6. The main point of the exercise is for you to see some of the different pieces of the system call machinery. Your new system call will get the current UTC time and return it to the user program. You may want to use the helper function,
cmostime()
(defined in
lapic.c
), to read the real time clock.
date.h
contains the definition of the
struct rtcdate
struct, which you will provide as an argument to
cmostime()
as a pointer.
You should create a user-level program that calls your new date system call; here’s some source you should put in
date.c
:
#include "types.h"#include "user.h"#include "date.h"intmain(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... exit();}
In order to make your new
date
program available to run from the xv6 shell, add_date
to theUPROGS
definition inMakefile
.Your strategy for making a date system call should be to clone all of the pieces of code that are specific to some existing system call, for example the “uptime” system call. You should grep for uptime in all the source files, using
grep -n uptime *.[chS]
.When you’re done, typing
date
to an xv6 shell prompt should print the current UTC time.Write down a few words of explanation for each of the files you had to modify in the process of creating your date system call.
Optional challenge: add a dup2() system call and modify the shell to use it.
第二步,我们要添加一个系统调用函数,使其可以返回当前系统时间。
我们要提前了解一下:
lapic.c
中定义了函数 cmostime()
来读取时钟时间。
void cmostime(struct rtcdate *r) {}
date.h
中定义了 rtcdate
结构体,作为参数提供给函数 cmostime()
。
struct rtcdate { uint second; uint minute; uint hour; uint day; uint month; uint year;};
了解完这些,我们就可以开始添加系统调用函数 date()
了:
在
syscall.h
中最后一行添加系统调用编号#define SYS_date 22
在
syscall.c
中添加系统调用函数的外部声明... [SYS_mkdir] "mkdir", [SYS_close] "close",// 以下为添加内容 [SYS_date] "date"};// 以上为添加内容// User code makes a system call with INT T_SYSCALL.// System call number in %eax....
...extern int sys_write(void);extern int sys_uptime(void);// 以下为添加内容extern int sys_date(void);// 以上为添加内容static int (*syscalls[])(void) = { [SYS_fork] sys_fork,...
... [SYS_mkdir] sys_mkdir, [SYS_close] sys_close,// 以下为添加内容 [SYS_date] sys_date,// 以上为添加内容};void syscall(void){ int num;...
在
user.h
中添加用户态函数的定义...int sleep(int);int uptime(void);// 以下为添加内容int date(struct rtcdate*);// 以上为添加内容// ulib.cint stat(char*, struct stat*);...
在
usys.S
中最后一行添加用户态函数的实现SYSCALL(date)
在
sysproc.c
中最后一行添加系统调用函数的实现// return current dateintsys_date(struct rtcdate *r){ if (argptr(0, (void *)&r, sizeof(*r)) < 0) return -1; cmostime(r); //从cmos中获取时间 return 0;}
至此,就完成了添加系统调用函数 date()
最后,我们需要添加使用这个系统调用函数的方法
新建文件 date.c
,并添加一下内容:
#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.month, r.day, r.year, r.hour, r.minute, r.second); exit();}
在 Makefile
中添加 UPROGS
对应命令的定义:
... _zombie\ _big\# 以下为添加内容 _date\# 以上为添加内容fs.img: mkfs README $(UPROGS) ./mkfs fs.img README $(UPROGS)...
至此,所有文件就修改完成了。
为了防止第一部分的输出影响我们时间的显示格式,可以先将 syscall.c
中的以下几行注释掉:
// static char SYS_call_names[][6] = {// [SYS_fork] "fork",...// [SYS_close] "close",// [SYS_date] "date"};
// cprintf("\tSYS_call: %s\tid: %d\n", SYS_call_names[num], num);
在Ubuntu虚拟机中编译运行:
$ make qemu-nox
然后输入命令 date
:
$ date10-20 2017 9:41:36
可以看到终端根据我们在 date.c
中写好的时间格式输出了UTC时间。
bingo~
参考资料:
Homework: xv6 system calls
MIT6.828 HW3: xv6 system calls
- [OS] Xv6 System Calls
- MIT6.828 HW3: xv6 system calls
- 【xv6学习之Lec8】System calls, Interrupts, and Exceptions
- [OS] Xv6 CPU Alarm
- xv6 Shell & OS organization
- xv6 System Call
- 8.1. System Calls
- Trace System Calls
- Linux System Calls
- Kernel System Calls
- Finding system calls
- Using System Calls
- [OS] Bigger Files For Xv6
- linux File-Handling System Calls
- Windos 7 SYSTEM CALLS (WINDOWS SSDT)
- Linux Kernel Interrupts, Exceptions and System Calls
- List of Linux/i386 system calls
- How system calls work in Linux
- 信号量处理有关的函数和数据结构
- 依赖新的库之后android studio编译报错
- python爬虫第六节课及作业答案
- Hyperledger Fabric 排序节点处理 Broadcast 请求的实现
- springboot junit 测试出现的错误
- [OS] Xv6 System Calls
- synchronized实现原理
- Java类的初始化块总结
- Android 6.0申请权限梳理(压制不住内心想当画家的心)
- spring使用aop时需要设置proxy-target-class="true" 否则无法依赖注入
- iOS window添加视频view或图片view,并有切换根视图控制器的时候注意
- list,set,map区别
- 外部访问 Vue 中的 methods方法及其属性
- 图的简单实现