xv6实验记录(二)
实验科目:操作系统原理及项目设计
实验题目:实验平台搭建和几个练手程序
实验时间:2023/9/25
友情链接: 友情链接
一、实验目的:
- 了解系统调用
二、实验内容:
- 完成
trace()
的新系统调用 - 完成
sysinfo()
的新系统调用
三、实验内容
(1)trace()系统调用的实现
(1)首先切换分支,保存实验记录,并清除编译记录
git checkout syscall
make clean
根据实验提示,在MakeFile文件中找到UPROGS
并添加$U/_trace\
打开user
目录可以看到存在一个user/trace.c
文件,观察该文件的源码:
if (trace(atoi(argv[1])) < 0) {
fprintf(2, "%s: trace failed\n", argv[0]);
exit(1);
}
看到这一段代码中存在trace()
方法的调用【该方法来自user.h】,trace函数接收一个int 类型的整数,返回值类型也是int,如果执行失败返回值为-1。
(2)在user/user.h
中添加函数原型
int trace(int); //NEW ADD
在user/usys.pl
中添加trace的入口
entry("trace"); //NEW ADD
在syscall.h
中添加宏定义
#define SYS_close 21
#define SYS_trace 22 //NEW ADD
(3)在proc结构体(在kernel/proc.h
)里面添加一个新变量用来存储跟踪号,然后在fork()的时候把结构体里新增加的变量也给复制过去,这样就达到了传参的目的。新的变量是不需要加锁的,因为只会被自己所在的进程使用,所以放在char name[16]
之后
修改kernel/proc.h
添加变量存储跟踪号
// Per-process state
struct proc {
// ...
// these are private to the process, so p->lock need not be held.
// ,,
char name[16];
char mask[23]; //NEW ADD
};
打开kernel/sysproc.c
添加一个trace函数的具体实现
uint64 //新添加的函数定义
sys_trace(void){
int n;
if(argint(0, &n) < 0) {
return -1;
}
struct proc *p = myproc();
char *mask = p->mask;
int i = 0;
while(i < 23 && n > 0){
if(n % 2){
mask[i++] = '1';
}else {
mask[i++] = '0';
}
n >>= 1;
}
return 0;
}
打开kernel/proc.c
文件修改fork()
函数在函数中添加一句 safestrcpy(np->mask, p->mask, sizeof(p->mask));
即可
int
fork(void)
{
int i, pid;
struct proc *np;
struct proc *p = myproc();
// Allocate process.
if((np = allocproc()) == 0){
return -1;
}
// Copy user memory from parent to child.
if(uvmcopy(p->pagetable, np->pagetable, p->sz) < 0){
freeproc(np);
release(&np->lock);
return -1;
}
np->sz = p->sz;
safestrcpy(np->mask, p->mask, sizeof(p->mask)); //NEW ADD
......
为了将trace打印出来,修改kernel/syscall.c
中的syscall()
函数
extern uint64 sys_trace(void); //NEW ADD
static uint64 (*syscalls[])(void) = {
// ...
[SYS_close] sys_close,
[SYS_trace] sys_trace, // NEW ADD
};
static char *syscall_names[23] = {"","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]();
if (strlen(p->mask) > 0 && p->mask[num] == '1'){ // NEW ADD
printf("%d: syscall %s -> %d\n", p->pid, syscall_names[num],p->trapframe->a0);
}
} else {
printf("%d %s: unknown sys call %d\n",
p->pid, p->name, num);
p->trapframe->a0 = -1;
}
}
测试效果
trace 32 grep hello README
trace 2147483647 grep hello README
./grade-lab-syscall trace
(2)sysinfo()系统调用的实现
(1)将$U/_sysinfotest
添加到 Makefile 中的 UPROGS
(2)在user/user.h
中声明sysinfo() 函数的原型,您需要预先声明struct sysinfo
的存在:修改user/user.h
需要在user.h里再声明一次struct sysinfo的原因是:在参数列表里的参数是看不见本文件外面定义的struct的。
struct stat;
struct rtcdate;
struct sysinfo; //New ADD
// system calls
// ...
int sysinfo(struct sysinfo *); //NEW ADD
(3)在user/usys.pl
中添加sysinfo的入口
entry("sysinfo"); //NEW ADD
(4)在syscall.h
中添加宏定义
#define SYS_close 21
#define SYS_trace 22
#define SYS_sysinfo 23
(5)修改kernel/syscall.c
中的syscall()
函数
extern uint64 sys_info(void);
static uint64 (*syscalls[])(void) = {
// ...
[SYS_sysinfo] sys_info,
};
static char* syscall_names[] = {
// ...
[SYS_sysinfo] "sys_info",
};
(6)编辑sysproc.c
文件,先添加函数体
uint64 sys_info(void) {
return 0;
}
(7)打开sysproc.c
文件添加\#include "sysinfo.h"
(8)要获得空闲内存的数目,请向kernel/kalloc.c
添加一个函数kfreemem
// get free memory bytes by count freelist
uint64 kfreemem(void) {
struct run *r;
uint64 count = 0;
acquire(&kmem.lock);
r = kmem.freelist;
while (r) {
r = r->next;
count++;
}
release(&kmem.lock);
return count * PGSIZE;
}
(9)要获得进程的数量,请在kernel/proc.c
中添加一个函数proc_num()
// get the number of processes whose state is not UNUSED
uint64 proc_num() {
struct proc *p;
uint64 count = 0;
for(p = proc; p < &proc[NPROC]; p++) {
acquire(&p->lock);
if(p->state != UNUSED) {
count++;
}
release(&p->lock);
}
return count;
}
(10)在kernel/defs.h
文件中添加函数原型
uint64 proc_num(void); //NEW ADD
uint64 kfreemem(void); //NEW ADD
(11)修改kernel/sysproc.c
文件的sys_info()
的函数体
uint64 sys_info(void) {
struct sysinfo info;
uint64 addr;
info.freemem = kfreemem();
info.nproc = proc_num();
if(argaddr(0, &addr) < 0) {
return -1;
}
// copy info(kernel space) to addr(user space)
if (copyout(myproc()->pagetable, addr, (char *)&info, sizeof(info)) < 0) {
return -1;
} else {
return 0;
}
}
测试效果
./grade-lab-syscall sysinfo
总测试
- 在xv6-lab-2021的目录下新建time.txt文件,之后输入一个整数代表你做实验的时间,单位是小时。之后就可以运行make grade来测试自己的成绩。
make grade //用来测试自己的实验成绩
如果上述测试失败,检查错误原因是否是因为
-
trace的打印格式有无错误
-
机器硬件不行,测试时间长,qemu认为超时【解决方法打开目录下的
gradelib.py
文件调整timeout时间】