comment added

This commit is contained in:
2025-06-23 11:18:49 +08:00
parent c7c962ffef
commit 70ee668b9b
6 changed files with 34 additions and 8 deletions

View File

@ -177,6 +177,7 @@ printfinit(void)
pr.locking = 1;
}
// 打印当前调用栈的返回地址,实现简单的函数回溯,用于调试。
void
backtrace(void)
{
@ -185,11 +186,12 @@ backtrace(void)
uint64 ra,fp = r_fp();//frame pointer -> address
uint64 pre_fp = *((uint64*)(fp - 16));
// 只要当前fp和上一个fp在同一页内就继续回溯
while(PGROUNDDOWN(fp)==PGROUNDDOWN(pre_fp)){
ra = *(uint64 *)(fp - 8);
printf("%p\n", (void*)ra);
fp = pre_fp;
pre_fp = *((uint64*)(fp - 16));
ra = *(uint64 *)(fp - 8); // 取出返回地址
printf("%p\n", (void*)ra); // 打印返回地址
fp = pre_fp; // 更新fp为上一个fp
pre_fp = *((uint64*)(fp - 16)); // 获取新的上一个fp
}
ra = *(uint64 *)(fp - 8);

View File

@ -132,6 +132,7 @@ found:
return 0;
}
// 为进程分配 pre_trapframe 空间,分配失败则释放进程资源并返回 0
if((p->pre_trapframe = (struct trapframe *)kalloc()) == 0){
freeproc(p);
release(&p->lock);
@ -166,6 +167,7 @@ freeproc(struct proc *p)
p->trapframe = 0;
if(p->pagetable)
proc_freepagetable(p->pagetable, p->sz);
// 如果进程的 pre_trapframe 存在,则释放其占用的内存,并将指针置为 0防止悬空指针。
if(p->pre_trapframe)
kfree((void*)p->pre_trapframe);
p->pre_trapframe = 0;

View File

@ -104,8 +104,8 @@ struct proc {
struct file *ofile[NOFILE]; // Open files
struct inode *cwd; // Current directory
char name[16]; // Process name (debugging)
int alarm_cnt; // Alarm count
int inter_cnt; // interrupts count
uint64 handler; // alarm func address
int alarm_cnt; // Alarm count 触发alarm的时钟中断数量
int inter_cnt; // interrupts count 需要统计的时钟中断的数量
uint64 handler; // alarm func address 记录处理alarm的函数的地址
struct trapframe *pre_trapframe;
};

View File

@ -338,6 +338,7 @@ r_ra()
return x;
}
// 读取当前帧指针s0寄存器的值
static inline uint64
r_fp()
{

View File

@ -94,6 +94,22 @@ sys_uptime(void)
return xticks;
}
// sys_sigalarm函数用于设置进程的定时信号处理机制。
// 参数:
// alarm_cnt定时器计数值表示每经过alarm_cnt个时钟中断后触发一次信号处理。
// addr信号处理函数的用户空间地址。
// 实现:
// 1. 通过argint和argaddr获取用户传入的参数。
// 2. 将进程的inter_cnt中断计数器清零。
// 3. 保存信号处理函数地址和定时器计数值到进程结构体。
// 4. 返回0表示设置成功。
// sys_sigreturn函数用于在信号处理函数执行完毕后恢复进程的上下文。
// 实现:
// 1. 获取当前进程指针。
// 2. 将trapframe恢复为信号处理前保存的pre_trapframe恢复进程上下文。
// 3. 将inter_cnt中断计数器清零重新计数。
// 4. 返回信号处理前a0寄存器的值作为系统调用的返回值。
uint64
sys_sigalarm(void)
{

View File

@ -76,13 +76,18 @@ usertrap(void)
if(killed(p))
exit(-1);
// give up the CPU if this is a timer interrupt.
// 如果这是一个定时器中断则让出CPU。
if(which_dev == 2){
// 当前进程的中断计数器加一。
p->inter_cnt++;
// 如果中断计数器达到设定的报警计数并且报警计数大于0。
if (p->inter_cnt == p->alarm_cnt && 0 < p->alarm_cnt) {
// 备份当前trapframe到pre_trapframe用于后续恢复。
*p->pre_trapframe = *p->trapframe;
// 将epc设置为用户定义的handler函数地址返回用户态时会跳转到handler执行。
p->trapframe->epc = p->handler;
} else {
// 否则让出CPU进行进程调度。
yield();
}
}