From a087b429dfa499d47b451961051b48f8fe485904 Mon Sep 17 00:00:00 2001 From: CGH0S7 <776459475@qq.com> Date: Tue, 25 Mar 2025 10:35:06 +0800 Subject: [PATCH] syscall trace finished --- answers-syscall.txt | 18 ++++++++++++++++++ grade-lab-syscall | 0 kernel/proc.c | 3 +++ kernel/proc.h | 2 ++ kernel/syscall.c | 4 +++- 5 files changed, 26 insertions(+), 1 deletion(-) create mode 100644 answers-syscall.txt mode change 100644 => 100755 grade-lab-syscall diff --git a/answers-syscall.txt b/answers-syscall.txt new file mode 100644 index 0000000..7986401 --- /dev/null +++ b/answers-syscall.txt @@ -0,0 +1,18 @@ +在xv6中,当执行到地址 `0x3ffffff11c` 处的 `sret` 指令时,特权级和执行流程的变化如下: + +1. **特权级变化** + - **执行前**:核心态(S模式,特权级 `1`) + - **执行后**:用户态(U模式,特权级 `0`) + `sret` 指令会从 `sstatus` 寄存器中恢复之前的特权级(由 `SPP` 位决定)。在进入陷阱处理时,处理器已自动将用户态的特权级(`0`)保存到 `sstatus.SPP`,因此 `sret` 会将特权级切换回用户态。 + +2. **恢复点地址** + 恢复点地址由 `sepc` 寄存器指定。在进入陷阱处理时,`sepc` 被设置为触发 `ecall` 的下一条指令地址(即 `0x14`)。因此,`sret` 执行后,程序会跳转到 `0x14` 处继续执行用户代码。 + +3. **执行的函数** + `sret` 返回后,用户程序会从 `0x14` 处继续执行。根据 `initcode.S` 的代码,`0x14` 是 `ecall` 指令的下一条地址。若 `exec` 系统调用成功,用户地址空间会被替换为新程序(如 `init`),此时 `sret` 返回后直接进入新程序的入口点。若 `exec` 失败(理论上不会发生),则会继续执行 `initcode.S` 中 `ecall` 后的代码(但实际代码中 `ecall` 后无其他指令)。 + +**总结** +- **特权级**:核心态(`1`)→ 用户态(`0`) +- **恢复点地址**:`0x14`(用户代码中 `ecall` 的下一条指令) +- **执行函数**:若 `exec` 成功,执行新程序(如 `init`);否则继续 `initcode.S` 的后续代码(实际无后续指令)。 + diff --git a/grade-lab-syscall b/grade-lab-syscall old mode 100644 new mode 100755 diff --git a/kernel/proc.c b/kernel/proc.c index a343244..db97edc 100644 --- a/kernel/proc.c +++ b/kernel/proc.c @@ -146,6 +146,9 @@ found: p->context.ra = (uint64)forkret; p->context.sp = p->kstack + PGSIZE; + // 初始化计数器 + memset(p->syscall_counts, 0, sizeof(p->syscall_counts)); + return p; } diff --git a/kernel/proc.h b/kernel/proc.h index 7eabad0..72b99e3 100644 --- a/kernel/proc.h +++ b/kernel/proc.h @@ -1,3 +1,4 @@ +#include "defs.h" // Saved registers for kernel context switches. struct context { uint64 ra; @@ -105,4 +106,5 @@ struct proc { struct file *ofile[NOFILE]; // Open files struct inode *cwd; // Current directory char name[16]; // Process name (debugging) + int syscall_counts[24]; // 每个系统调用的调用次数 }; diff --git a/kernel/syscall.c b/kernel/syscall.c index 3c81e5f..9d267af 100644 --- a/kernel/syscall.c +++ b/kernel/syscall.c @@ -147,7 +147,9 @@ syscall(void) // and store its return value in p->trapframe->a0 p->trapframe->a0 = syscalls[num](); if (p->tracemask & (1 << num)) { - printf("%d: syscall %s -> %d\n",p->pid, syscalls_name[num], p->trapframe->a0); + p->syscall_counts[num]++; + printf("%d: syscall %s(trace counts: %d) -> %d\n", + p->pid, syscalls_name[num], p->syscall_counts[num], p->trapframe->a0); } } else { printf("%d %s: unknown sys call %d\n",