从零写OS(五十四):完整信号系统——sigaction、mask 与 sigreturn

跑 busybox sh 时发现一个诡异的问题:Ctrl+C 能杀掉进程,但 handler 执行完之后程序直接崩了——寄存器全乱了。调查下去,发现 ch53 的信号系统有三个根本缺陷。 问题一:寄存器没有保存 ch53 的 signal_dispatch 只保存了 user_rip 和 user_rsp: uint64_t new_rsp = *user_rsp - 8; *(uint64_t *)(phys + ...) = *user_rip; // 仅压返回地址 *user_rsp = new_rsp; *user_rip = handler; handler 执行期间会用到 r15, r14, …, rbx, rbp——这些全都没有保存。handler 返回时弹出的 rip 确实是原来的位置,但所有调用者保存的寄存器都被 handler 破坏了,接下来的代码跑的是垃圾数据。 问题二:sigaction 是空 stub case SYS_SIGACTION: case SYS_SIGPROCMASK: case SYS_SIGRETURN: return 0; // 什么都没做 musl 的 signal() 底层调用 sigaction,返回 0 让它以为设置成功了,实际上 handler 根本没有注册进去。 问题三:没有 signal mask handler 执行期间,如果同一个信号再次到来,会再次触发 dispatch,handler 递归执行,栈很快就溢出了。 解法:signal_frame_t + 真正的 sigaction 核心数据结构 把所有寄存器打包成一个结构体,压到用户栈: ...

June 8, 2026 · 3 min · 大飞
京ICP备14031575号-3