它存储在内核堆栈中。Linux syscall的入口代码非常复杂,特别是现在它正在执行一些幽灵和崩溃缓解,但是你可以看看entry_SYSCALL_64的定义。
具体地说,这个序列将userland线程的状态保存到内核堆栈。它正在构造struct pt_regs结构的最后一部分,稍后将传递给do_syscall_64。
代码语言:javascript复制/* Construct struct pt_regs on stack */
pushq $__USER_DS /* pt_regs->ss */
pushq PER_CPU_VAR(cpu_tss_rw + TSS_sp2) /* pt_regs->sp */ // This is where it's put on the stack.
pushq %r11 /* pt_regs->flags */
pushq $__USER_CS /* pt_regs->cs */
pushq %rcx /* pt_regs->ip */
GLOBAL(entry_SYSCALL_64_after_hwframe)
pushq %rax /* pt_regs->orig_ax */
PUSH_AND_CLEAR_REGS rax=$-ENOSYS至于ss寄存器,在x86有虚拟内存之前,就有了段的概念。每个程序将存在于它自己的一系列内存段中。每个段寄存器(ss、gs等)将索引保存到全局描述符表中,该表确定了段的起始位置和它拥有的权限。ss保存堆栈的段。如果您尝试推入、弹出或调用(如果esp指向堆栈段之外),您将得到一个分段异常。如今,除了fs和gs分别用于访问用户空间和内核空间中的线程本地数据外,x86_64 ss和大多数其他分段寄存器都是残留的。