optinal load_avg to fix
This commit is contained in:
1
Makefile
1
Makefile
@ -195,6 +195,7 @@ UPROGS=\
|
|||||||
$U/_find\
|
$U/_find\
|
||||||
$U/_xargs\
|
$U/_xargs\
|
||||||
$U/_trace\
|
$U/_trace\
|
||||||
|
$U/_sysinfo\
|
||||||
$U/_sysinfotest\
|
$U/_sysinfotest\
|
||||||
|
|
||||||
|
|
||||||
|
|||||||
@ -1,18 +1,18 @@
|
|||||||
在xv6中,当执行到地址 `0x3ffffff11c` 处的 `sret` 指令时,特权级和执行流程的变化如下:
|
在xv6中,当执行到地址 0x3ffffff11c 处的 sret 指令时,特权级和执行流程的变化如下:
|
||||||
|
|
||||||
1. **特权级变化**
|
1. 特权级变化
|
||||||
- **执行前**:核心态(S模式,特权级 `1`)
|
- 执行前:核心态(S模式,特权级 1)
|
||||||
- **执行后**:用户态(U模式,特权级 `0`)
|
- 执行后:用户态(U模式,特权级 0)
|
||||||
`sret` 指令会从 `sstatus` 寄存器中恢复之前的特权级(由 `SPP` 位决定)。在进入陷阱处理时,处理器已自动将用户态的特权级(`0`)保存到 `sstatus.SPP`,因此 `sret` 会将特权级切换回用户态。
|
sret 指令会从 sstatus 寄存器中恢复之前的特权级(由 SPP 位决定)。在进入陷阱处理时,处理器已自动将用户态的特权级(0)保存到 sstatus.SPP,因此 sret 会将特权级切换回用户态。
|
||||||
|
|
||||||
2. **恢复点地址**
|
2. 恢复点地址
|
||||||
恢复点地址由 `sepc` 寄存器指定。在进入陷阱处理时,`sepc` 被设置为触发 `ecall` 的下一条指令地址(即 `0x14`)。因此,`sret` 执行后,程序会跳转到 `0x14` 处继续执行用户代码。
|
恢复点地址由 sepc 寄存器指定。在进入陷阱处理时,sepc 被设置为触发 ecall 的下一条指令地址(即 0x14)。因此,sret 执行后,程序会跳转到 0x14 处继续执行用户代码。
|
||||||
|
|
||||||
3. **执行的函数**
|
3. 执行的函数
|
||||||
`sret` 返回后,用户程序会从 `0x14` 处继续执行。根据 `initcode.S` 的代码,`0x14` 是 `ecall` 指令的下一条地址。若 `exec` 系统调用成功,用户地址空间会被替换为新程序(如 `init`),此时 `sret` 返回后直接进入新程序的入口点。若 `exec` 失败(理论上不会发生),则会继续执行 `initcode.S` 中 `ecall` 后的代码(但实际代码中 `ecall` 后无其他指令)。
|
sret 返回后,用户程序会从 0x14 处继续执行。根据 initcode.S 的代码,0x14 是 ecall 指令的下一条地址。若 exec 系统调用成功,用户地址空间会被替换为新程序(如 init),此时 sret 返回后直接进入新程序的入口点。若 exec 失败(理论上不会发生),则会继续执行 initcode.S 中 ecall 后的代码(但实际代码中 ecall 后无其他指令)。
|
||||||
|
|
||||||
**总结**
|
综上所述
|
||||||
- **特权级**:核心态(`1`)→ 用户态(`0`)
|
- 特权级:核心态(1)→ 用户态(0)
|
||||||
- **恢复点地址**:`0x14`(用户代码中 `ecall` 的下一条指令)
|
- 恢复点地址:0x14(用户代码中 ecall 的下一条指令)
|
||||||
- **执行函数**:若 `exec` 成功,执行新程序(如 `init`);否则继续 `initcode.S` 的后续代码(实际无后续指令)。
|
- 执行函数:若 exec 成功,执行新程序(如 init);否则继续 initcode.S 的后续代码(实际无后续指令)。
|
||||||
|
|
||||||
|
|||||||
@ -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);
|
int either_copyin(void *dst, int user_src, uint64 src, uint64 len);
|
||||||
void procdump(void);
|
void procdump(void);
|
||||||
int proc_size(void);
|
int proc_size(void);
|
||||||
|
int get_current_load(void);
|
||||||
|
void update_load_avg(void);
|
||||||
|
|
||||||
// swtch.S
|
// swtch.S
|
||||||
void swtch(struct context *, struct context *);
|
void swtch(struct context *, struct context *);
|
||||||
|
|||||||
@ -6,6 +6,8 @@
|
|||||||
#include "proc.h"
|
#include "proc.h"
|
||||||
#include "defs.h"
|
#include "defs.h"
|
||||||
|
|
||||||
|
uint64 load_avg = 0;
|
||||||
|
|
||||||
struct cpu cpus[NCPU];
|
struct cpu cpus[NCPU];
|
||||||
|
|
||||||
struct proc proc[NPROC];
|
struct proc proc[NPROC];
|
||||||
@ -701,3 +703,23 @@ proc_size()
|
|||||||
}
|
}
|
||||||
return n;
|
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));
|
||||||
|
}
|
||||||
|
|||||||
@ -1,4 +1,8 @@
|
|||||||
#include "defs.h"
|
#include "defs.h"
|
||||||
|
#define ALPHA 0.9
|
||||||
|
|
||||||
|
extern uint64 load_avg;
|
||||||
|
|
||||||
// Saved registers for kernel context switches.
|
// Saved registers for kernel context switches.
|
||||||
struct context {
|
struct context {
|
||||||
uint64 ra;
|
uint64 ra;
|
||||||
|
|||||||
@ -152,7 +152,7 @@ syscall(void)
|
|||||||
p->syscall_counts[num]++;
|
p->syscall_counts[num]++;
|
||||||
printf("%d: syscall %s(trace counts: %d) -> %d\n",
|
printf("%d: syscall %s(trace counts: %d) -> %d\n",
|
||||||
p->pid, syscalls_name[num], p->syscall_counts[num], p->trapframe->a0);
|
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 {
|
} else {
|
||||||
printf("%d %s: unknown sys call %d\n",
|
printf("%d %s: unknown sys call %d\n",
|
||||||
|
|||||||
@ -3,4 +3,5 @@ struct sysinfo {
|
|||||||
uint64 freemem;
|
uint64 freemem;
|
||||||
uint64 nproc;
|
uint64 nproc;
|
||||||
uint64 unused_proc_num;
|
uint64 unused_proc_num;
|
||||||
|
uint64 load_avg;
|
||||||
};
|
};
|
||||||
|
|||||||
@ -110,10 +110,12 @@ sys_sysinfo(void)
|
|||||||
uint64 addr;
|
uint64 addr;
|
||||||
argaddr(0, &addr);
|
argaddr(0, &addr);
|
||||||
if (addr < 0) return -1;
|
if (addr < 0) return -1;
|
||||||
|
/*update_load_avg();*/
|
||||||
struct proc* p = myproc();
|
struct proc* p = myproc();
|
||||||
info.nproc = proc_size();
|
info.nproc = proc_size();
|
||||||
info.freemem = freemem();
|
info.freemem = freemem();
|
||||||
info.unused_proc_num = NPROC - info.nproc;
|
info.unused_proc_num = NPROC - info.nproc;
|
||||||
|
info.load_avg = load_avg;
|
||||||
if (copyout(p->pagetable, addr, (char*)&info, sizeof(info)) < 0)
|
if (copyout(p->pagetable, addr, (char*)&info, sizeof(info)) < 0)
|
||||||
return -1;
|
return -1;
|
||||||
return 0;
|
return 0;
|
||||||
|
|||||||
21
user/sysinfo.c
Normal file
21
user/sysinfo.c
Normal file
@ -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);
|
||||||
|
}
|
||||||
@ -6,24 +6,19 @@ int
|
|||||||
main(int argc, char *argv[])
|
main(int argc, char *argv[])
|
||||||
{
|
{
|
||||||
int i;
|
int i;
|
||||||
//存储待跟踪程序的名称和参数
|
|
||||||
char *nargv[MAXARG];
|
char *nargv[MAXARG];
|
||||||
|
|
||||||
//保证trace的参数不少于三个,并且跟踪的系统调用号在0-99之间
|
|
||||||
if(argc < 3 || (argv[1][0] < '0' || argv[1][0] > '9')){
|
if(argc < 3 || (argv[1][0] < '0' || argv[1][0] > '9')){
|
||||||
fprintf(2, "Usage: %s mask command\n", argv[0]);
|
fprintf(2, "Usage: %s mask command\n", argv[0]);
|
||||||
exit(1);
|
exit(1);
|
||||||
}
|
}
|
||||||
//调用trace系统调用,传入待跟踪系统调用号
|
|
||||||
if (trace(atoi(argv[1])) < 0) {
|
if (trace(atoi(argv[1])) < 0) {
|
||||||
fprintf(2, "%s: trace failed\n", argv[0]);
|
fprintf(2, "%s: trace failed\n", argv[0]);
|
||||||
exit(1);
|
exit(1);
|
||||||
}
|
}
|
||||||
//保存待跟踪程序的名称和参数
|
|
||||||
for(i = 2; i < argc && i < MAXARG; i++){
|
for(i = 2; i < argc && i < MAXARG; i++){
|
||||||
nargv[i-2] = argv[i];
|
nargv[i-2] = argv[i];
|
||||||
}
|
}
|
||||||
//运行待跟踪的程序
|
|
||||||
exec(nargv[0], nargv);
|
exec(nargv[0], nargv);
|
||||||
exit(0);
|
exit(0);
|
||||||
}
|
}
|
||||||
|
|||||||
Reference in New Issue
Block a user