进程控制块栈指针指向及内核栈相关技术疑问
关于进程栈与内核栈的疑问解答
一、存储过程/系统调用参数及调用地址的栈:用户栈还是内核栈?
首先明确每个进程拥有独立的用户栈和内核栈,二者作用场景不同:
- 对于用户态的普通过程(函数)调用:参数、局部变量、返回地址均存储在用户栈中,这是用户栈的核心职责之一。比如80×86架构下,执行
call指令时,CPU会自动把下一条指令的地址(返回地址)压入用户栈,再跳转到目标函数执行,你之前“用户栈不承担存储调用地址职责”的理解有误。 - 对于系统调用:过程会涉及两个栈的配合:
《Operating Systems: Internals and Design Principles, 9e》表3.5的描述涵盖了两种场景:用户态过程调用用用户栈,系统调用则结合用户栈与内核栈。
用户态发起系统调用前,可能将参数存入用户栈(或特定寄存器);触发系统调用(如int 0x80或syscall指令)后,CPU切换到内核态,此时会把用户态的关键寄存器(如用户栈指针esp、指令指针eip等)压入内核栈,同时内核通过页表映射访问用户栈读取系统调用参数,执行内核逻辑。系统调用的返回地址(用户态下一条指令地址)会保存在内核栈中,退出内核态时恢复到eip寄存器。
二、内核是否会将内核页表的部分内容复制到进程的内核栈?
答案是不会,原因如下:
《Understanding The Linux Kernel 3e》提到的“进程从用户态切换到内核态后内核栈初始为空”,指的是每个进程的内核栈首次被使用时为空;之后每次进入内核态,都会把用户态的现场数据(寄存器值、返回地址等)压入内核栈,退出时弹出恢复。
- 内核页表是内核管理虚拟地址到物理地址映射的结构,属于内核空间的核心数据结构,内核通过页表访问用户或内核空间内存,无需将页表内容复制到内核栈。
- 进程需要调用地址(如系统调用返回地址)时,是在进入内核态的瞬间由CPU自动将用户态的
eip(下一条指令地址)压入内核栈,而非通过复制页表内容实现。内核栈的作用是保存内核态下的函数调用栈帧、现场寄存器值,与页表功能完全无关。
三、整体理解修正总结
- 用户栈负责存储用户态下函数调用的参数、返回地址、局部变量;
- 内核栈负责存储内核态下的函数调用栈帧、用户态现场数据(寄存器、返回地址);
- 系统调用跨两个栈运作:参数可能来自用户栈,现场数据保存到内核栈,返回时从内核栈恢复用户态现场;
- 内核页表与内核栈是完全独立的结构,不存在复制页表内容到内核栈的操作。
内容的提问来源于stack exchange,提问作者3088 K
相关产品推荐
相关产品推荐

