MIT 6.S081 Lab2

System call trace

In this assignment you will add a system call tracing feature that may help you when debugging later labs. You’ll create a new trace system call that will control tracing. It should take one argument, an integer “mask”, whose bits specify which system calls to trace. For example, to trace the fork system call, a program calls trace(1 << SYS_fork), where SYS_fork is a syscall number from kernel/syscall.h. You have to modify the xv6 kernel to print out a line when each system call is about to return, if the system call’s number is set in the mask. The line should contain the process id, the name of the system call and the return value; you don’t need to print the system call arguments. The trace system call should enable tracing for the process that calls it and any children that it subsequently forks, but should not affect other processes.

整体流程图
在这里插入图片描述
本次实验要添加一个系统调用trace

这个系统调用可以为每一个进程添加一个位mask,用来指定要为哪些系统调用输出调试信息

如何新添加一个系统调用

其实这个流程已经在上面的图讲的很清除了,这里我用文字描述一下

第一步

首先,我们要在user/user.h上添加trace函数的声明,使得用户态程序可以找到跳板入口函数
在这里插入图片描述

第二步

user/usys.pl脚本中加入entry("trace")函数,这是从用户态到内核态的跳板函数

在这里插入图片描述
这个脚本会生成risc-v汇编代码user/usys.S

user/usys.S

 trace:		# 定义用户态跳板函数
 li a7, SYS_trace	# 将系统调用 id 存入 a7 寄存器
 ecall				# ecall,调用 system call ,跳到内核态的统一系统调用处理函数 syscall()  (syscall.c)
 ret

在这里插入图片描述

第三步

接着,我们要在kernel/syscall.h中添加sys_trace的序号
在这里插入图片描述

然后,我们要在kernel/syscall.c中外部全局声明新的内核调用函数sys_trace
在这里插入图片描述
然后,我们要在kernel/syscall.c的映射表syscalls中添加一个编号系统调用指针
在这里插入图片描述
ok, 以上都讲完了,我们来看看系统调用的整个流程

  • user/user.h: 用户态程序调用跳板函数 trace()
  • user/usys.S 跳板函数 trace() 使用 CPU 提供的 ecall 指令,调用到内核态
  • kernel/syscall.c 到达内核态统一系统调用处理函数 syscall(),所有系统调用都会跳到这里来处理。
  • kernel/syscall.c syscall() 根据跳板传进来的系统调用编号,查询 syscalls[] 表,找到对应的内核函数并调用。
  • kernel/sysproc.c 到达 sys_trace() 函数,执行具体内核操作

具体代码的实现

在`proc结构里,添加一个mask,这个mask会记录要去trace的system call

//kernel/proc.h

// Per-process state
struct proc {
   
  struct spinlock lock;

  // p->lock must be held when using these:
  enum procstate state;        // Process state
  struct proc *parent;         // Parent process
  void *chan;                  // If non-zero, sleeping on chan
  int killed;                  // If non-zero, have been killed
  int xstate;                  // Exit status to be returned to parent's wait
  int pid;                     // Process ID

  // these are private to the process, so p->lock need not be held.
  uint64 kstack;               // Virtual address of kernel stack
  uint64 sz;                   // Size of process memory (bytes)
  pagetable_t pagetable;       // User page table
  struct trapframe *trapframe; // data page for trampoline.S
  struct context context;      // swtch() here to run process
  struct file *ofile[NOFILE];  // Open files
  struct inode *cwd;           // Current directory
  char name[16];               // Process name (debugging)
  int mask;	               //存储跟踪号
  //fork的时候会把结构体里新增的变量也给复制进去,达到了传参的作用
  //新的变量不需要加锁,因为只会被自己所在的进程使用
};

实现sys_trace 函数

//kernel/sysproc.c

uint64 sys_trace(void){
   
  int n;
  //argint()用于读取在a0-a5寄存器中传递的系统调用参数
  if(argint(0,&n)<0){
   
    return -1;
  }
  //myproc()函数获取当前进程的struct proc,即PCB
  myproc()->mask=n;
  return 0;
}

添加 np->mask=p->mask;

//kernel/proc.c

// Create a new process, copying the parent.
// Sets up child kernel stack to return as if from fork() system call.
int
fork(void)
{
   
  int i,<
  • 4
    点赞
  • 8
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值