首页 > 其他分享 >Lab2_syscall

Lab2_syscall

时间:2022-10-26 21:25:47浏览次数:76  
标签:kernel 函数 trace syscall mask Lab2 user

 

操作系统实验报告


 

lab2 【System calls】


  

    

 

学生姓名:jeekzhang

 

学 号:20307130XXX

 

专 业:计算机科学与技术

一、实验内容:

Part A System call trace

编译准备:

  • Add $U/_trace to UPROGS in Makefile

    2022-10-11 15-05-10 的屏幕截图-1665967904969

  • Add a prototype for the system call to user/user.h

    2022-10-11 15-06-01 的屏幕截图

  • Add a stub to user/usys.pl

2022-10-11 15-06-07 的屏幕截图

  • Add a syscall number to kernel/syscall.h

    2022-10-11 15-06-22 的屏幕截图

  • 编译测试:make qemu,成功运行

    2022-10-11 15-06-37 的屏幕截图

实现trace:

  • 实现思路:

    根据提示,是要在kernel/sysproc.c中添加一个函数 sys_trace(),该函数要记住传进来的参数,并在struct proc中新加一个变量用于储存这一参数。结合前面的功能描述,这个参数就是mask,也即trace 32 grep hello README中的32

    查看kernel/sysproc.c中其他函数(如sys_exit()),发现其没有参数,但使用了argint(0,&n)来获取所需的n值,其用于获取第0个寄存器的信息并用n来储存。故mask也应该用同样的方法来读取。

    2022-10-17 09-20-01 的屏幕截图

    同时要在struct proc中添加mask变量

    2022-10-17 09-29-48 的屏幕截图

    再把mask赋值给当前procmask,根据sys_getpid(),可用myproc()->mask来进行赋值。

  • 编写函数:先读取0号寄存器的内容到mask中,再把mask赋给当前procmask

    2022-10-17 09-34-44 的屏幕截图

子项复制:

  • Modify fork() (see kernel/proc.c) to copy the trace mask from the parent to the child process.

    即把父进程的mask赋给子进程:

    2022-10-17 09-35-50 的屏幕截图

打印输出:

  • syscall()中添加相应的trace项:

2022-10-17 09-36-18 的屏幕截图

2022-10-17 09-36-25 的屏幕截图

  • Add an array of syscall names to index into.

    用于打印输出

    2022-10-17 09-36-51 的屏幕截图

  • 输出实现:

    首先,打印内容的结构是:3: syscall read -> 1023(3为pid,syscall为统一输出,read为系统调用的名字,1023为其返回值。

    pid直接用myproc()->pid即可获取

    系统调用的名字则通过上述的表中根据编号(num)获取,编号要与mask进行匹配,匹配成功才要进行输出,mask的第num位为1则需打印输出。匹配过程考虑位运算,将1左移num位,再&mask,若当mask的第num位不为1时,结果为0。

    返回值调用syscalls[num]()后即得到,因p->trapframe->a0存储了该值,输出它即可。

    2022-10-17 09-37-08 的屏幕截图

测试:

2022-10-17 11-39-04 的屏幕截图

2022-10-17 11-39-47 的屏幕截图

Part B Sysinfo

编译准备:

  • 重复Part A的操作:

    2022-10-15 10-40-27 的屏幕截图

    2022-10-15 10-59-08 的屏幕截图

    2022-10-15 11-00-07 的屏幕截图

    2022-10-17 10-20-13 的屏幕截图

  • 其他准备:

    Predeclare the existence of struct sysinfo

    2022-10-17 10-53-30 的屏幕截图

    Add Student ID for print

    2022-10-17 11-00-51 的屏幕截图

辅助函数:

To collect the amount of free memory, add a function to kernel/kalloc.c

阅读 kernel/kalloc.c中的其他函数发现,有freelist可以使用,用一个while循环遍历该freelist,并让计数器count++,即可获取free的page数目,count*PGSIZE即为free memory。同时,涉及到临界区变量,该过程要加锁。

2022-10-17 10-58-37 的屏幕截图

To collect the number of processes, add a function to kernel/proc.c

copy kernel/kalloc.c中的其他函数的遍历方法,并置计数器count,当状态不为UNUSED即count++,该过程也要加锁。

2022-10-17 10-59-20 的屏幕截图

实现sysinfo:

  • 实现思路:

    先创建一个struct sysinfo

    调用之前两个辅助函数获取sysinfo内的freememnproc值,

    再把学号赋值给sid并打印

    接下来进行copyout操作,将对应位置改为info即可,注意前面参数的获取也要有,p通过myproc()获取,addr从0号寄存器读入。

  • 编写函数:注意要在"defs.h"添加辅助函数的定义

    2022-10-17 11-00-34 的屏幕截图

测试:

2022-10-17 11-41-22 的屏幕截图

二、问题回答:

(1)System calls Part A部分,简述一下trace全流程.

trace先调用user/trace.c进行参数读入和预处理,再通过entry(trace)从用户态转到内核态,执行后续操作。在内核态中具体调用sys_trace()函数,该函数从0号寄存器中读入所谓的mask,并将mask放入mypro()mask中。当进行syscall()时,就会根据myproc()mask是否与编号num匹配来打印相应内容,完成trace

(2)kernel/syscall.h是干什么的,如何起作用的?

通过宏定义,将系统调用函数的名字作为标识符替换为数字编号。通过编号转化后,就可以将系统调用名字的数据转为数据放入寄存器(a7)中,当syscall需要时便从寄存器中读取编号,从而执行对应函数。

(3)命令 “trace 32 grep hello README”中的trace字段是用户态下的还是实现的系统调用函数trace?

trace字段应是在用户态下的函数user/trace.c,通过内核调用sys_trace()来实现具体操作。

三、问题解决:

【问题】在Part B的调用两个辅助函数获取sysinfo内的freememnproc值时,出现错误,显示函数没有定义。

2022-10-15 14-39-38 的屏幕截图

如上图的getfreemem()函数,其在kernel/kalloc.c中实现。其定义按道理应添加在kernel/kalloc.h中,然后include该.h文件即可,但并没有该.h文件。经代码搜索后发现kernel/kalloc.c中函数的定义是在defs.h中声明的,类似于user/user.h,故应在 "defs.h"添加辅助函数的定义。2022-10-18 08-51-34 的屏幕截图

2022-10-18 08-51-30 的屏幕截图

四、实验感想:

  1. 通过这次实验具体函数的实现,理解了用户态和内核态的区别与关系,以及用户态是如何转到内核态的,这是在代码层面一直困扰我的问题。

  2. 这次实验还有一个地方有点颠覆我的认知,就是内核函数获取参数不是像之前写的代码那样靠传参,而是直接从寄存器中读。

五、实验参考:

  1. Lab: System calls (mit.edu)
  2. kernel/syscall.c 的几个小函数简介

标签:kernel,函数,trace,syscall,mask,Lab2,user
From: https://www.cnblogs.com/jeekzhang/p/16830072.html

相关文章