From 2001e8e478bf2d16f47035651157593c24a03ea7 Mon Sep 17 00:00:00 2001 From: CGH0S7 <776459475@qq.com> Date: Wed, 26 Mar 2025 09:32:27 +0800 Subject: [PATCH] optinal load_avg to fix --- Makefile | 1 + answers-syscall.txt | 26 +++++++++++++------------- kernel/defs.h | 2 ++ kernel/proc.c | 22 ++++++++++++++++++++++ kernel/proc.h | 4 ++++ kernel/syscall.c | 2 +- kernel/sysinfo.h | 1 + kernel/sysproc.c | 2 ++ time.txt | 2 +- user/sysinfo.c | 21 +++++++++++++++++++++ user/trace.c | 5 ----- 11 files changed, 68 insertions(+), 20 deletions(-) create mode 100644 user/sysinfo.c diff --git a/Makefile b/Makefile index 034219f..cd90f07 100644 --- a/Makefile +++ b/Makefile @@ -195,6 +195,7 @@ UPROGS=\ $U/_find\ $U/_xargs\ $U/_trace\ + $U/_sysinfo\ $U/_sysinfotest\ diff --git a/answers-syscall.txt b/answers-syscall.txt index 7986401..b3c107c 100644 --- a/answers-syscall.txt +++ b/answers-syscall.txt @@ -1,18 +1,18 @@ -在xv6中,当执行到地址 `0x3ffffff11c` 处的 `sret` 指令时,特权级和执行流程的变化如下: +在xv6中,当执行到地址 0x3ffffff11c 处的 sret 指令时,特权级和执行流程的变化如下: -1. **特权级变化** - - **执行前**:核心态(S模式,特权级 `1`) - - **执行后**:用户态(U模式,特权级 `0`) - `sret` 指令会从 `sstatus` 寄存器中恢复之前的特权级(由 `SPP` 位决定)。在进入陷阱处理时,处理器已自动将用户态的特权级(`0`)保存到 `sstatus.SPP`,因此 `sret` 会将特权级切换回用户态。 +1. 特权级变化 + - 执行前:核心态(S模式,特权级 1) + - 执行后:用户态(U模式,特权级 0) + sret 指令会从 sstatus 寄存器中恢复之前的特权级(由 SPP 位决定)。在进入陷阱处理时,处理器已自动将用户态的特权级(0)保存到 sstatus.SPP,因此 sret 会将特权级切换回用户态。 -2. **恢复点地址** - 恢复点地址由 `sepc` 寄存器指定。在进入陷阱处理时,`sepc` 被设置为触发 `ecall` 的下一条指令地址(即 `0x14`)。因此,`sret` 执行后,程序会跳转到 `0x14` 处继续执行用户代码。 +2. 恢复点地址 + 恢复点地址由 sepc 寄存器指定。在进入陷阱处理时,sepc 被设置为触发 ecall 的下一条指令地址(即 0x14)。因此,sret 执行后,程序会跳转到 0x14 处继续执行用户代码。 -3. **执行的函数** - `sret` 返回后,用户程序会从 `0x14` 处继续执行。根据 `initcode.S` 的代码,`0x14` 是 `ecall` 指令的下一条地址。若 `exec` 系统调用成功,用户地址空间会被替换为新程序(如 `init`),此时 `sret` 返回后直接进入新程序的入口点。若 `exec` 失败(理论上不会发生),则会继续执行 `initcode.S` 中 `ecall` 后的代码(但实际代码中 `ecall` 后无其他指令)。 +3. 执行的函数 + sret 返回后,用户程序会从 0x14 处继续执行。根据 initcode.S 的代码,0x14 是 ecall 指令的下一条地址。若 exec 系统调用成功,用户地址空间会被替换为新程序(如 init),此时 sret 返回后直接进入新程序的入口点。若 exec 失败(理论上不会发生),则会继续执行 initcode.S 中 ecall 后的代码(但实际代码中 ecall 后无其他指令)。 -**总结** -- **特权级**:核心态(`1`)→ 用户态(`0`) -- **恢复点地址**:`0x14`(用户代码中 `ecall` 的下一条指令) -- **执行函数**:若 `exec` 成功,执行新程序(如 `init`);否则继续 `initcode.S` 的后续代码(实际无后续指令)。 +综上所述 +- 特权级:核心态(1)→ 用户态(0) +- 恢复点地址:0x14(用户代码中 ecall 的下一条指令) +- 执行函数:若 exec 成功,执行新程序(如 init);否则继续 initcode.S 的后续代码(实际无后续指令)。 diff --git a/kernel/defs.h b/kernel/defs.h index 2c07dbe..cbe6d66 100644 --- a/kernel/defs.h +++ b/kernel/defs.h @@ -108,6 +108,8 @@ int either_copyout(int user_dst, uint64 dst, void *src, uint64 len); int either_copyin(void *dst, int user_src, uint64 src, uint64 len); void procdump(void); int proc_size(void); +int get_current_load(void); +void update_load_avg(void); // swtch.S void swtch(struct context *, struct context *); diff --git a/kernel/proc.c b/kernel/proc.c index 863b57d..668bccb 100644 --- a/kernel/proc.c +++ b/kernel/proc.c @@ -6,6 +6,8 @@ #include "proc.h" #include "defs.h" +uint64 load_avg = 0; + struct cpu cpus[NCPU]; struct proc proc[NPROC]; @@ -701,3 +703,23 @@ proc_size() } return n; } + +int +get_current_load() { + struct proc *p; + int current_load = 0; + + for (p = proc; p < &proc[NPROC]; p++) { + if (p->state == RUNNING || p->state == RUNNABLE) { + current_load++; + } + } + + return current_load; +} + +void +update_load_avg() { + int current_load = get_current_load(); + load_avg = (load_avg * ALPHA) + (current_load * (1 - ALPHA)); +} diff --git a/kernel/proc.h b/kernel/proc.h index 72b99e3..e220702 100644 --- a/kernel/proc.h +++ b/kernel/proc.h @@ -1,4 +1,8 @@ #include "defs.h" +#define ALPHA 0.9 + +extern uint64 load_avg; + // Saved registers for kernel context switches. struct context { uint64 ra; diff --git a/kernel/syscall.c b/kernel/syscall.c index 5c578d0..320cdaf 100644 --- a/kernel/syscall.c +++ b/kernel/syscall.c @@ -152,7 +152,7 @@ syscall(void) 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); - printf("a1:%d a2:%d a3:%d\n",p->trapframe->a1,p->trapframe->a2,p->trapframe->a3); + printf("a1:%d a2:%d a3:%d a4:%d a5:%d a6:%d a7:%d\n",p->trapframe->a1,p->trapframe->a2,p->trapframe->a3,p->trapframe->a4,p->trapframe->a5,p->trapframe->a6,p->trapframe->a7); } } else { printf("%d %s: unknown sys call %d\n", diff --git a/kernel/sysinfo.h b/kernel/sysinfo.h index 670db98..4548f34 100644 --- a/kernel/sysinfo.h +++ b/kernel/sysinfo.h @@ -3,4 +3,5 @@ struct sysinfo { uint64 freemem; uint64 nproc; uint64 unused_proc_num; + uint64 load_avg; }; diff --git a/kernel/sysproc.c b/kernel/sysproc.c index ddad0ea..f114934 100644 --- a/kernel/sysproc.c +++ b/kernel/sysproc.c @@ -110,10 +110,12 @@ sys_sysinfo(void) uint64 addr; argaddr(0, &addr); if (addr < 0) return -1; + /*update_load_avg();*/ struct proc* p = myproc(); info.nproc = proc_size(); info.freemem = freemem(); info.unused_proc_num = NPROC - info.nproc; + info.load_avg = load_avg; if (copyout(p->pagetable, addr, (char*)&info, sizeof(info)) < 0) return -1; return 0; diff --git a/time.txt b/time.txt index 7ed6ff8..b8626c4 100644 --- a/time.txt +++ b/time.txt @@ -1 +1 @@ -5 +4 diff --git a/user/sysinfo.c b/user/sysinfo.c new file mode 100644 index 0000000..d862256 --- /dev/null +++ b/user/sysinfo.c @@ -0,0 +1,21 @@ +#include "kernel/param.h" +#include "kernel/types.h" +#include "kernel/stat.h" +#include "user/user.h" + +int main() { + struct sysinfo info; + + if (sysinfo(&info) < 0) { + printf("sysinfo: failed to retrieve system information\n"); + exit(1); + } + + printf("System Information:\n"); + printf(" Free Memory: %d bytes\n", info.freemem); + printf(" Number of Processes: %d\n", info.nproc); + printf(" Unused Process Slots: %d\n", info.unused_proc_num); + printf(" Load Average: %d\n", info.load_avg); + + exit(0); +} diff --git a/user/trace.c b/user/trace.c index 386bfc1..ef6f4d5 100644 --- a/user/trace.c +++ b/user/trace.c @@ -6,24 +6,19 @@ int main(int argc, char *argv[]) { int i; - //存储待跟踪程序的名称和参数 char *nargv[MAXARG]; - //保证trace的参数不少于三个,并且跟踪的系统调用号在0-99之间 if(argc < 3 || (argv[1][0] < '0' || argv[1][0] > '9')){ fprintf(2, "Usage: %s mask command\n", argv[0]); exit(1); } - //调用trace系统调用,传入待跟踪系统调用号 if (trace(atoi(argv[1])) < 0) { fprintf(2, "%s: trace failed\n", argv[0]); exit(1); } - //保存待跟踪程序的名称和参数 for(i = 2; i < argc && i < MAXARG; i++){ nargv[i-2] = argv[i]; } - //运行待跟踪的程序 exec(nargv[0], nargv); exit(0); }