6.1810-system calls
本文最后更新于:2024年3月5日 上午
接下来我们要开始看系统调用的真面目啦
Using gdb
这次算是我第一次认真gdb了,之前都是直接用vsc封装好的调试的
对于我的环境wsl ubuntu20.04来说这里还有一些小坑
需要启动riscv-gdb,设置架构,手动连接端口并加载符号表
qemu的端口号和kernel符号表的位置可能会有所不同(?,这里是chat老师的样例,不过用vsc remote的话端口号是好找的(
1 |
|
1 |
|
不过反正是自学所以也没有ta查,就随便往txt里写了点
- Threads call usertrap()
1 |
|
- reg a7 represent SYSCALL type
1 |
|
- sstatus means Supervisor status register , previous privilege is user mode
SPP (Supervisor previous privilege) = 0
SIE (Supervisor Interrupt Enable) = 1
1 |
|
so variable num in reg a3
sepc=0x0000000080002050
num = * (int *) 0;
80002050: 00002683 lw a3,0(zero) # 0 <_entry-0x80000000>In xv6 , 0-0x1000 is Unused.
It’s confirmed by scause:
scause 0x000000000000000d means Load Page Fault
1 |
|
trace
通过掩码来追踪系统调用
这个掩码需要记录在进程信息中,所以在kernel/proc.h中的struct proc中添加
1 |
|
在内核的系统调用过程中(kernel/syscall.c)处理掩码
1 |
|
根据已经处理好的用户态的trace实现,去补全sys_trace()函数
1 |
|
注意使用argint向内核态传参
接下来确保子进程会继承追踪掩码,在kernel/proc.c中的fork函数中添加
1 |
|
sysinfo
在内核态收集信息(进程和内存)之后将结构体复制到用户态即可。
遍历proc数组收集进程数量
1 |
|
遍历链表收集内存
1 |
|
最后通过copyout将数据拷贝到内核态的相应地址
1 |
|