mit6.s081 lab2: system calls
1.system call tracing(moderate)
要求:创建一个系统调用来实现跟踪特性,它采用一个参数来指定跟踪哪一个系统调用,例如:跟踪fork系统调用,程序调用trace(1<<SYS_fork),其中SYS_fork是kernel/syscall.h中的系统调用号。如果在掩码中设置了系统调用的编号,则必须修改须
xv6的内核,以便在每个系统调用即将返回时输出一行。这一行应包括进程id、系统调用的名称和返回值。不需要打印系统调用参数。用于跟踪的系统调用应能够跟踪调用它的进程以及随后的子进程,但不能影响其它的进程。
要实现的效果:
trace 32 grep hello README,表示执行grep hello README时,read系统调用发生时,跟踪并打印要求的东西。
$ trace 32 grep hello README
3: syscall read -> 1023
3: syscall read -> 966
3: syscall read -> 70
3: syscall read -> 0
这里32表示的是1<<SYS_read的结果。
提示:
- 在makefile中添加$U/_trace
- 这个时候直接运行make qemu会发现无法编译user/trace.c,trace这个系统调用还没有实现,即在用户态下的存根还不存在。要在user/user.h中将系统调用声明出来(即int trace(int)),在user/usys.pl中添加存根(entry("trace")),在 kernel/syscall.h中添加系统调用号。
这里Makefile 调用 perl 脚本 user/usys.pl,它生成 user/usys.S,即实际的系统调用存根,它使用 RISC-V 中的ecall回调指令转换到内核。
在完成了上面的操作之后就算是修复了编译问题了,这时可以成功的make qemu了。一旦修复了编译问题,就运行trace 32 grep hello README; 它将失败,因为您还没有在内核中实现系统调用。 - 在 kernel/sysproc.c 中添加 sys _ trace ()函数,该函数通过在 proc 结构中的新变量中记住参数来实现新的系统调用(参见 kernel/proc.h)。从用户空间检索系统调用参数的函数在 kernel/syscall.c 中,您可以在 kernel/sysproc.c 中看到它们的使用示例。(没看太明白,但是可以以照猫画虎的做)
- 修改 fork ()(参见 kernel/proc.c) ,将跟踪掩码从父进程复制到子进程。
- 修改 kernel/syscall.c 中的 syscall ()函数以打印跟踪输出。您需要添加要索引到的系统调用名称数组。
可以知道的信息:
在根据提示完成相关的文件配置之后,可以知道目前需要在kernel/sysproc.c中来完成sys_trace()这个函数。
根据提示三以及参考sysproc.c中的其它函数,先大致做一个测试:
uint64
sys_trace(void)
{
printf("sys_trace:hi\n");
return 0;
}
当运行trace 32 grep hello README的时候可以看到输出就是我们在sys_trace中所打印的东西,就也意味着这里要实现trace系统调用被调用时要输出的东西。
再根据提示三中的从用户空间检索系统调用参数的函数在 kernel/syscall.c 中,转到syscall.c中最下面可以看到syscall函数.在这个函数中首先定义了一个整型的num来记录一个参数,当if判断不成功的时候它会打印“pid(进程号) name(所传入的调用名字):unknown sys call”这样的信息,那么大致可以知道当if判断成功的时候,应该就是对要执行的系统调用做处理,由于每次调用成功会去找到syscalls[num],那么可以推测是根据num来判断是哪一个系统调用,因此不妨再写一个存放系统调用名字的数组来打印一下试试

这时make qemu试一下,可以发现随着xv6的启动,调用的系统调用被打印出来,如下图所示:

这个时候就可以明确syscall是调用系统函数的一个入口,sys_trace是处理trace系统调用的地方,有了这两个函数就应该可以实现这个实验所要实现的效果。
在实现sys_trace函数的时候发现在其它的函数中都有这么一段代码:
int n;
if(argint(0, &n) < 0)
return -1;
那么继续照猫画虎,把这一段搬到sys_trace中用输出调试一下,即printf("sys_trace:hi,n is %d\n",n);,可以发现这段代码是把用户态得到的掩码传给n,比如trace 32 grep hello README得到的n就是32,这个n用于决定要追踪的函数,那么现在的问题就是:如何让syscall也可以获得这个值,毕竟在syscall中需要这个掩码来打印对应得系统调用。
这个时候再返回到提示三中,有这样一句话:在 kernel/sysproc.c 中添加 sys _ trace ()函数,该函数通过在 proc 结构体中的新变量中记住参数来实现新的系统调用(参见 kernel/proc.h),按照这个提示,我们应该在proc中添加变量来实现两个函数共用这一掩码值,而proc结构体所存得是每一个进程的状态信息。
到了这里,基本功能都能实现了,但是我们发现提示4:“修改 fork ()(参见 kernel/proc.c) ,将跟踪掩码从父进程复制到子进程”好像一直没有用到,于是去查看proc.c中的fork,发现在这里面有两个结构体np和p,我们需要将父进程p的相关信息复制给np,于是添加一行:np->trace_mask=p->trace_mask;
实现:
对syscall的修改
static char* syscall_names[]={
"fork","exit","wait","pipe","read","kill","exec","fstat","chdir",
"dup","getpid","sbrk","sleep","uptime","open","write","mknod",
"unlink","link","mkdir","close","trace"
};
void
syscall(void)
{
int num;
struct proc *p = myproc();
num = p->trapframe->a7;
if(num > 0 && num < NELEM(syscalls) && syscalls[num]) {
p->trapframe->a0 = syscalls[num]();//返回值放在a0这个寄存器中
int mask=p->trace_mask;
if((mask>>num)&1){
printf("%d: syscall %s -> %d\n",p->pid,syscall_names[num-1],p->trapframe->a0);
}
} else {
printf("%d %s: unknown sys call %d\n",
p->pid, p->name, num);
p->trapframe->a0 = -1;
}
}
对sys_trace的修改:
uint64
sys_trace(void)
{
int mask;//n是从用户态传进来的掩码,比如追踪的是fork传进来的就是32
if(argint(0, &mask) < 0)
return -1;
//printf("sys_trace:hi,n is %d\n",mask);
struct proc *p = myproc();
p->trace_mask=mask;//把掩码放到进程信息中
return 0;
}
补充:
在测试grep hello README的时候发现输出和预期的不太一样,在这里输出了上一次所跟踪的信息,后来发现在proc.c中根据注释发现有一个freeproc函数用于释放进程信息,我们需要在里面添加一行p->proc_mask=0

2.sysinfo(moderate)
要求:写一个sysinfo这个system call,需要获取当前空闲的内存大小填入struct sysinfo.freemem中,获取当前所有不是UNUSED的进程数量填入struct sysinfo.nproc中
提示:
- 在makefile中添加$U/_sysinfotest
- 运行 make qemu; user/sysinfotest.c 将无法编译。添加系统调用 sysinfo,步骤与前面的任务相同。要在 user/user.h 中声明 sysinfo ()的原型,需要预先声明 struct sysinfo 的存在:
struct sysinfo;
int sysinfo(struct sysinfo *);
- Sysinfo 需要将一个 struct sysinfo 复制回用户空间; 请参阅 sys _ fstat ()(kernel/sysfile.c)和 filestat ()(kernel/file.c)以获得如何使用 copy out ()实现这一点的示例。
- 要收集空闲内存量,请向 kernel/kalloc.c 添加一个函数
- 要收集进程数,请向 kernel/proc.c 添加一个函数
- 在sysproc.c中完成系统调用函数的编写,在syscall中记得对syscalls修改并extern
- 和前面一样先要在user/user.h中声明system callint sysinfo(struct sysinfo *)以及struct sysinfo,在user/usys.pl中注册entry,在kernel/syscall.h中注册一个syscall number,在kernel/sysproc.c中对uint64 sys_sysinfo(void)进行实现,注意要在sysproc.c中添加头文件sysinfo.h
实现:
sysproc.c中实现系统调用
uint64
sys_sysinfo(void)
{
struct sysinfo info;
uint64 addr;
struct proc *p=myproc();
info.freemem=acquire_freemem();
info.nproc=acquire_nproc();
if(argaddr(0, &addr) < 0)//入参放到addr里
return -1;
if(copyout(p->pagetable, addr, (char *)&info, sizeof(info)) < 0)//函数运算后的info结果放到addr里
return -1;
return 0;
}
kalloc.c中实现获取空闲内存
uint64 acquire_freemem()
{
struct run *r;
uint64 cnt=0;
acquire(&kmem.lock);
r = kmem.freelist;
while(r)
{
r=r->next;
cnt++;//链表的长度就是页表的个数
}
release(&kmem.lock);
return cnt*PGSIZE;//页表的个数乘以页表的大小就是整个系统空闲内存的大小
}
proc.c中实现获取使用进程数
uint64 acquire_nproc()
{
struct proc *p;
int cnt=0;
for(p = proc; p < &proc[NPROC]; p++) {
acquire(&p->lock);
if(p->state != UNUSED) {
cnt++;
}
release(&p->lock);
}
return cnt;
}
3测试结果

mit6.s081 lab2: system calls的更多相关文章
- MIT 6.828 JOS学习笔记18. Lab 3.2 Part B: Page Faults, Breakpoints Exceptions, and System Calls
现在你的操作系统内核已经具备一定的异常处理能力了,在这部分实验中,我们将会进一步完善它,使它能够处理不同类型的中断/异常. Handling Page Fault 缺页中断是一个非常重要的中断,因为我 ...
- Hooking Android System Calls for Pleasure and Benefit
The Android kernel is a powerful ally to the reverse engineer. While regular Android apps are hopele ...
- MIT6.S081/6.828 实验1:Lab Unix Utilities
Mit6.828/6.S081 fall 2019的Lab1是Unix utilities,主要内容为利用xv6的系统调用实现sleep.pingpong.primes.find和xargs等工具.本 ...
- MIT-6.828-JOS-lab5:File system, Spawn and Shell
Lab 5: File system, Spawn and Shell tags: mit-6.828 os 概述 本lab将实现JOS的文件系统,只要包括如下四部分: 引入一个文件系统进程(FS进程 ...
- MIT6.828 Lab2 内存管理
Lab2 0. 任务介绍 你将编写一个内存管理代码.主要分为两大部分.分别对物理内存和虚拟内存的管理. 对于物理内存,每次分配内存分配器会为你分配4096bytes.也称为一个页(在大部分操作系统中一 ...
- 【MIT6.S081/6.828】手把手教你搭建开发环境
目录 1. 简介 2. 安装ubuntu20.04 3. 更换源 3.1 更换/etc/apt/sources.list文件里的源 3.2 备份源列表 3.3 打开sources.list文件修改 3 ...
- Linux Kernel sys_call_table、Kernel Symbols Export Table Generation Principle、Difference Between System Calls Entrance In 32bit、64bit Linux
目录 . sys_call_table:系统调用表 . 内核符号导出表:Kernel-Symbol-Table . Linux 32bit.64bit环境下系统调用入口的异同 . Linux 32bi ...
- Linux Kernel sys_call_table、Kernel Symbols Export Table Generation Principle、Difference Between System Calls Entrance In 32bit、64bit Linux【转】
转自:http://www.cnblogs.com/LittleHann/p/4127096.html 目录 1. sys_call_table:系统调用表 2. 内核符号导出表:Kernel-Sym ...
- Linux System Calls Hooking Method Summary
http://www.cnblogs.com/LittleHann/p/3854977.html http://www.cnblogs.com/cozy/articles/3175615.html h ...
- MIT6.828 JOS系统 lab2
MIT6.828 LAB2:http://pdos.csail.mit.edu/6.828/2014/labs/lab2/ LAB2里面主要讲的是系统的分页过程,还有就是简单的虚拟地址到物理地址的过程 ...
随机推荐
- Oracle ADG容灾端部署Rman备份的一些实践经验
随着数据库中数据量的不断增加.业务的复杂性提高.各种政策颁布的系统容灾等级要求,数据库备份的工作及备份文件的有效性及备份文件的管理变得愈发重要.在Oracle数据库中提供了强大的备份和恢复工具,其中R ...
- 做数据分析,我们需要懂多少excel知识?
数据分析所需的Excel知识详解 在进行数据分析工作时,Excel是一个非常常用且强大的数据处理工具.以下是数据分析中常用的Excel知识点和技巧的详细描述. 1. 基本操作 在使用Excel进行数据 ...
- VideoPipe可视化视频结构化框架更新总结(2023-12-5)
项目地址:https://github.com/sherlockchou86/video_pipe_c 往期文章:https://www.cnblogs.com/xiaozhi_5638/p/1696 ...
- Fast ORM 读写分离功能使用方式
Fast Framework 作者 Mr-zhong 代码改变世界.... 一.前言 Fast Framework 基于NET6.0 封装的轻量级 ORM 框架 支持多种数据库 SqlServer O ...
- AtCoder_abc331
AtCoder_abc331 (这次题真的真的真的好难) 比赛链接 A - Tomorrow 题目链接 题目大意 有一个\(M\)个月,\(D\)天的日历,请输出\(y年m月z日\)的下一天. 解题思 ...
- VScode怎么实现c的运行,这里只讲述一些细节
第一下载的Vscode要设置信任模式,否则你后面搞什么都没有用 第二下载minGw还是gcc 都行 第三安装插件,c,c++. 然后编译就行了,我搞了一天,主要弹出的是未找到exe文件,但是我告诉大家 ...
- 踩坑:nacos启动报错提示需要设置JDK环境 ,报错:ERROR: Please set the JAVA_HOME variable in your environment, We need java(x64)! jdk8 or later is better! !!
换了个Windows11的新电脑,因为个人工作.学习需要,就重新下载了Nacos并解压使用,结果就踩了个坑,使用下面命令启动Nacos服务端时: startup.cmd -m standalone 直 ...
- springcloud 实体类使用@Builder@AllArgsConstructor两个注解后查询执行操作时报数据转换异常
异常日志如下: org.springframework.jdbc.UncategorizedSQLException: Error attempting to get column 'DATA_SOU ...
- Scrapy-CrawlSpider爬虫类使用案例
CrawlSpider类型的爬虫会根据指定的rules规则自动找到url比自动爬取. 优点:适合整站爬取,自动翻页爬取 缺点:比较难以通过meta传参,只适合一个页面就能拿完数据的. import s ...
- lottie 动画在 vue 中的使用
前言 最近我所负责的项目中,我采用了动画效果,并开始使用 gif 来实现.然而,在实践过程中,我发现 gif 格式的动画在 git 中出现了明显的锯齿感,这让我非常困扰.为了追求更完美的表现效果,我最 ...