You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

x32架构下信号处理:siginfo与ucontext为何通过寄存器传递?

x32架构信号处理函数参数传递的疑惑解答

问题核心梳理

你说的没错,x32用户态常规调用约定确实是通过栈传递参数,但在x32_setup_rt_frame这段内核代码里,却把信号处理函数的siginfo_t*和ucontext_t*参数放到了si和dx寄存器中——这看起来和常规逻辑矛盾,其实是因为信号处理的调用规则是内核特殊定义的,并不完全遵循x32用户态的常规传参约定。

为什么用寄存器传参?

x32本质是运行在64位模式下的32位指针变种,Linux内核在实现x32的RT信号处理时,并没有重新设计一套传参逻辑,而是复用了x86-64的信号处理传参规则:

  • 第一个参数(信号编号)存入rdi寄存器(对应代码里的regs->di = ksig->sig)
  • 第二个参数(siginfo_t*)存入rsi寄存器(代码里的regs->si = (unsigned long) &frame->info)
  • 第三个参数(ucontext_t*)存入rdx寄存器(代码里的regs->dx = (unsigned long) &frame->uc)

信号处理是内核直接触发的用户态函数调用,内核有权决定参数的传递方式,这样做既能和x86-64的信号处理逻辑保持一致,减少代码冗余,也能保证处理效率。

信号处理函数如何获取参数?

用户态的x32信号处理函数(尤其是带SA_SIGINFO标志的RT信号处理函数)在定义时,编译器会自动适配内核的传参规则:

void my_rt_sig_handler(int sig, siginfo_t *info, ucontext_t *uc) {
    // sig会从rdi寄存器读取
    // info会从rsi寄存器读取
    // uc会从rdx寄存器读取
}

也就是说,编译器知道信号处理函数是内核直接调用的特殊入口,会生成从对应寄存器取参的代码,而不是像常规函数那样从栈上读取参数。

栈帧frame的实际作用

你提到的rt_sigframe_x32结构体(变量frame)并不是用来传递参数的,它的核心作用是:

  • 保存用户态的上下文信息(比如寄存器状态、信号掩码),方便信号处理完成后恢复现场
  • 存储siginfo_t的具体数据和ucontext_t结构,寄存器里只是存放了这些结构的指针
  • 存放信号处理结束后的恢复代码(pretcode),确保处理完成后能正确回到原执行流程

总结

x32架构下的信号处理调用是内核定制的特殊规则,复用了x86-64的寄存器传参方式,而非x32用户态常规的栈传参。寄存器中存放的是栈帧内结构体的指针,信号处理函数直接从寄存器读取这些指针,进而访问栈帧里的具体数据。

内容的提问来源于stack exchange,提问作者taoozh

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.05.14 07:05:50