6.s081 第二周实验

6.s081 第二周实验,第1张

6.s081 第二周实验 第二周实验1 :trace trace函数: 参数为一个整数mask。他的bit为1的位置决定了需要trace的syscall函数,比如trace 32, 32 = 100000, 1所在的位置是第5位(从0开始,右往左),查看syscall.h文件,编号为5的函数是sys_read(). 因此trace 32 xxx。 会打印xxx命令中涉及read函数的信息

过程:

Add $U/_trace to UPROGS in Makefile

在user/user.h中添加 trace的声明

int trace(int);

在user/usys.pl添加, usys.pl会生成汇编usys.S,而这个usys.S会使用ecall进入内核

entry("trace");

在kernel/syscall.h中为trace添加一个号码

#define SYS_trace  22

在 kernel/sysproc.c 添加并实现 sys_trace(), 需要使用一个结构体proc (见 kernel/proc.h)。从用户空间获取system calls参数的方法在kernel/syscall.c, 可以在kernel/sysproc.c找到它们的使用实例。

uint64 sys_trace(void) {
 int mask;
 argint(0, &mask);
 struct proc* proc = myproc();
 proc->tracemask = mask;
 return 0;
}

修改 fork() 将proc中新的变量也复制到child里面

np->tracemask = p->tracemask;

修改kernel/syscall.c中的 syscall() ,添加一个保存了函数名的结构体,print语句

static char* syscallsname[] = {
[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",
[SYS_trace]   "trace",
[SYS_sysinfo] "sys_sysinfo",
};



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 store return value

   // start 
   if(p->tracemask & (1< %dn",p->pid,syscallsname[num],p->trapframe->a0);
   }
   // end 
 } else {
   printf("%d %s: unknown sys call %dn",
           p->pid, p->name, num);
   p->trapframe->a0 = -1;
 }
}
部分源码说明:

kernel/proc.h: 定义了一个结构体proc(还有其他结构体),用以保存进程的状态信息. 如给定p为该进程的proc结构体指针。则:

p->pagetable可得到该进程的虚拟页表。p->kstack可得到两个栈,每个进程均有用户栈和内核栈,用户模式下使用用户栈,仅当进程通过system call 或 interrupt进入内核时才能使用内核栈p->state可获取进程的状态 实验二 sysinfo

前面流程和trace一致,修改Makefile,在user/user.h,user/usys.pl,kernel/syscall.h添加信息。
sysinfo记录的是 可用进程数空闲内存, 这两个属性封装在一个结构体(见kernel/sysinfo.h)

计算可用进程数nproc:
参考 kernel/proc.c 中的allocproc函数。 在 kernel/proc.c 中添加:

  int proc_num(void) {
  	struct proc *p;
 	int num = 0;
 	for(p = proc; p < &proc[NPROC]; p++) {
 		if(p -> state != UNUSED) {
   			num++;
 		}
 	}
 	return num;
 }```
计算空闲内存,参考kernel/kalloc.c中的函数kalloc,kernel/kalloc.c在文件末尾添加:
	int freemem_size() {
		 struct run *r;
   		 int num = 0;
   		 r = kmem.freelist;
   		 while(r) {
   		    num++;
   		    r = r->next;
 		}
		return num * PGSIZE;
   	}

在kernel/def.h中添加声明:

// for sys_info
int freemem_size(void);
int proc_num(void);

需要在内核中将这些信息返回到用户态,参考sys_fstat() (kernel/sysfile.c) and filestat() (kernel/file.c)中的copyout用法, 在sys_proc.c中添加:

uint64 sys_sysinfo(void) {
  struct sysinfo sys_info;
  sys_info.freemem = freemem_size();
  sys_info.nproc = proc_num();
  struct proc *p = myproc();

  uint64 addr; 
  if(argaddr(0, &addr) < 0)
    return -1;
  if(copyout(p->pagetable, addr, (char *)&sys_info, sizeof(sys_info)) < 0)
      return -1;
  return 0;
}

欢迎分享,转载请注明来源:内存溢出

原文地址: https://outofmemory.cn/zaji/5704261.html

(0)
打赏 微信扫一扫 微信扫一扫 支付宝扫一扫 支付宝扫一扫
上一篇 2022-12-17
下一篇 2022-12-17

发表评论

登录后才能评论

评论列表(0条)

保存