【MIT 6.S081】Lab2: System Calls
MIT 6.S081的Lab2: System calls题解
System call tracing (moderate)
要求
添加一个系统调用追踪函数,有一个整数参数为mask,二进制指定需要追踪的系统调用(也许是多个),打印进程id:系统调用名->返回值
,
分析
添加系统调用的步骤
-
即为用户空间添加该系统调用的入口:
-
在
/user/user.h
中添加函数声明 -
在
/user/usys.pl
中添加入口entry("xxx");
-
在
kernel/syscall.h
中定义系统调用号 -
在
kernel/syscall.c
的syscalls
函数指针数组中添加对应的函数,则可以根据头文件里的系统调用号调用相应函数
实现本题的系统调用
-
在
kernel/proc.h
中为进程添加变量记录trace的系统调用编号 -
在
kernel/sysproc.c
中添加一个sys_trace()
函数 -
修改
kernel/proc.c
中fork()
函数,将系统调用编号提供给子进程 -
在
kernel/sysproc.c
中添加sys_trace()
,从寄存器中获得参数(即想追踪的系统调用mask)设置到当前的进程 -
修改
kernel/syscall.c
中的syscall
函数打印trace的信息,这里我卡了一下没仔细看提示,一开始直接用了proc类中的name,后来发现那个是进程名不是系统调用名字,所以另开一个字符串数组放入系统调用的名字,用系统调用的序号直接找到它输出
可能用到的函数
-
int argint(int n, int *p)
在kernel/sysproc.c
中的函数大都使用,意思是获取第n
个寄存器的值,将指针p指向它的值(并非指向寄存器,这里值是由另一个函数返回来的) -
myproc()
:返回一个proc类的指针,指向当前进程,可以用它来完成mask赋值 -
static uint64 argraw(int n)
:返回对应的寄存器内容(trap前)
实现
编辑Makefile
文件,在UPROGS=\
一栏添加如下内容:
1 | $U/_trace\ |
在/user/user.h
添加系统调用函数声明(参数是int
可以从/user/trace.c
中的调用看出来):
1 | // system calls |
在/user/usys.pl
添加:
1 | entry("trace"); |
在kernel/syscall.h
添加:
1 |
在kernel/syscall.c
的syscalls
函数指针数组中补充内容:
1 | extern uint64 sys_trace(void); |
在kernel/proc.h
中为进程添加变量mask
来记录(一旦有调用trace)提供的系统调用编号:
1 | // Per-process state |
在kernel/proc.c
中修改fork()
函数,将mask提供给子进程:
1 | int fork(void) { |
在kernel/sysproc.c
中添加一个sys_trace()
函数:
1 | // set current process mask |
修改kernel/syscall.c
,添加系统调用函数名的字符串数组,以及修改syscall
函数打印trace的信息:
1 | static const char* sysname[] = { "", |
测试
输入命令:
1 | sudo python3 grade-lab-syscall trace |
Sysinfo (moderate)
要求
添加一个sysinfo
系统调用,参数是一个kernel/sysinfo.h
中的结构体sysinfo
指针,系统调用补充指针指向这个结构体的字段内容
分析
sysinfo结构体
-
freemem
:空闲内存的字节数 -
nproc
:正在运行(state
的内容不是UNUSED,proc的定义在/kernel/proc.h
)的进程数
流程
- 与第一个题目中的分析相同
可能用到的函数
-
拷贝的过程
-
copyout(pagetable_t pagetable, uint64 dstva, char *src, uint64 len)
:从内核拷贝内容到用户层,从src
拷贝len
字节到虚拟地址dstva
在页表pagetable
指向的位置,成功返回 ,否则返回 -
还需要用上一个题中
syscall.c
中的函数(argint
拿整数,argaddr
拿指针) -
proc结构体里有页表信息
-
-
获取空闲内存
kernel/kalloc.c
中的kalloc()
:kmen
有个空闲列表,空闲列表的大小应该是宏定义的PGSIZE
,补充一个函数,用同样的写法统计空闲列表的个数,就得到结果了
-
获取进程数:
kernel/proc.c
中的static struct proc* allocproc(void)
:模仿这个函数中分配进程的过程进行统计
实现
编辑Makefile
文件,在UPROGS=\
一栏添加如下内容:
1 | $U/_sysinfotest\ |
在/user/user.h
添加系统调用函数声明(文档有提示):
1 | // system calls |
在/user/usys.pl
添加:
1 | entry("sysinfo"); |
在kernel/syscall.h
添加:
1 |
在kernel/syscall.c
的syscalls
函数指针数组和函数名数组中补充内容:
1 | extern uint64 sys_sysinfo(void); |
根据上述分析写出kernel/sysproc.c
中的sys_sysinfo()
:
1 | uint64 sys_sysinfo(void) { |
其中get_freemem()
函数写在kernel/kalloc.c
中,记得补充函数声明到defs.h
头文件中:
1 | // in defs.h |
其中get_nproc()
函数写在kernel/proc.c
中,记得补充函数声明到defs.h
头文件中:
1 | // in defs.h |
测试
输入命令:
1 | sudo python3 grade-lab-syscall sysinfotest |