「Sigaction 挑战性任务」为什么进程控制块会变成预期之外的值?

杨振炜(助教)
🔖︎ 11 订阅
👍︎ 11 点赞

TL;DR

你需要将 kern/env.c 文件中 env_run 函数的末尾修改为:

1
2
3
- env_pop_tf(&curenv->env_tf, curenv->env_asid);
+ struct Trapframe tmp_tf = curenv->env_tf;
+ env_pop_tf(&tmp_tf, curenv->env_asid);

原因剖析

考察原代码以下调用链:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
schedule(yield)
|
> env_run(e);
|
+-> env_run(e)
|
> env_pop_tf(&curenv->env_tf, curenv->env_asid)
|
+-> env_pop_tf([a0], a1)
|
> move [sp], [a0]
> j ret_from_exception
|
+-> ret_from_exception
|
> move [a0], [sp]
> jal do_signal
|
+-> do_signal([tf]) // seek for unhandled signal
| |
| > ...
|
> eret

不难发现,被方括号标记的参数和寄存器都指向进程控制块内部的地址。在进入 do_signal 时,sp 寄存器指向 curenv 中的某个地址,而从 do_signal 开始就将 sp 及以下的区域当成栈使用了。进程控制块里也就会出现栈上的非预期值了。

解决这个问题也很简单:在向 env_pop_tf 传参时不使用进程控制块的地址就可以了。可以将 curenv->env_tf 复制到当前的栈上,再传入栈上的地址,此即是上文中给出的修改方式。

Thinking

为什么不能将 curenv->env_tf 复制到 (struct Trapframe *)KSTACKTOP - 1

回复主题帖

Roisy
👍︎ 0 点赞

神!!!
自己debug的时候真的没往这个方向考虑过……
(啊啊啊为什么我现在才看到这条,直接55->100了

回复主题帖

张昀祥
👍︎ 0 点赞

神!
压哨冲刺100全靠您🧎‍♂️🧎‍♂️🧎‍♂️

0%