用户栈和内核栈

举报
王建峰 发表于 2021/11/19 00:22:10 2021/11/19
【摘要】 特此说明: 刘超的趣谈linux操作系统是比较重要的参考资料,本文大部分内容和所有图片来源于这个专栏。 00、说明背景 在程序执行过程中,一旦调用到系统调用,就需要进入内核继续执行。无论是进...

特此说明: 刘超的趣谈linux操作系统是比较重要的参考资料,本文大部分内容和所有图片来源于这个专栏。

00、说明背景

在程序执行过程中,一旦调用到系统调用,就需要进入内核继续执行。无论是进程还是线程,对应到内核里面,我们统一都叫任务(Task),由一个统一的结构 task_struct 进行管理。
其中,内核栈是和进程运行有关系的。相关的成员变量有

  • 用户态函数栈,内核态函数栈栈的组成
  • 进程从用户态到内核态的上下文切换
  • 内核态中通过stask_struct管理内核栈

01、用户态函数栈

在数据结构中学过的栈模型,是一种高度抽象的设计。函数调用和返回也是按照栈的思想来设计的,在虚拟内存空间中自上而下分配。具体在32系统和64系统的实现方式,略微不同
32位系统

我们先来看 32 位操作系统的情况。在 CPU 里,ESP(Extended Stack Pointer)是栈顶指针寄存器,入栈操作 Push 和出栈操作 Pop 指令,会自动调整 ESP 的值。另外有一个寄存器 EBP(Extended Base Pointer),是栈基地址指针寄存器,指向当前栈帧的最底部。
.
例如,A 调用 B,A 的栈里面包含 A 函数的局部变量,然后是调用 B 的时候要传给它的参数,然后返回 A 的地址,这个地址也应该入栈,这就形成了 A 的栈帧。接下来就是 B 的栈帧部分了,先保存的是 A 栈帧的栈底位置,也就是 EBP。因为在 B 函数里面获取 A 传进来的参数,就是通过这个指针获取的,接下来保存的是 B 的局部变量等等。
.
当 B 返回的时候,返回值会保存在 EAX 寄存器中,从栈中弹出返回地址,将指令跳转回去,参数也从栈中弹出,然后继续执行 A。

64位系统

64 位操作系统的寄存器数目比较多。rax 用于保存函数调用的返回结果。栈顶指针寄存器变成了 rsp,指向栈顶位置。堆栈的 Pop 和 Push 操作会自动调整 rsp,栈基指针寄存器变成了 rbp,指向当前栈帧的起始位置。
.
改变比较多的是参数传递。rdi、rsi、rdx、rcx、r8、r9 这 6 个寄存器,用于传递存储函数调用时的 6 个参数。如果超过 6 的时候,还是需要放到栈里面。
.
然而,前 6 个参数有时候需要进行寻址,但是如果在寄存器里面,是没有地址的,因而还是会放到栈里面,只不过放到栈里面的操作是被调用函数做的。

02、内核态函数栈

进程通过函数调用进入内核态,内核中也有函数调用,也有一个内核栈。

arch/x86/include/asm/page_32_types.h或者arch/x86/include/asm/page_64_types.h定义了内核栈大小THREAD_SIZE

  • thread_info结构是对 task_struct 结构的补充,往往与体系结构有关的,都放在 thread_info 里面。
  • 在内核代码里面有这样一个 union,将 thread_info 和 stack 放在一起,在include/linux/sched.h文件中就有。
  • pt_regs结构,在系统从用户态切换到内核态的时候,将用户态上下文信息保存到这里。在32系统和64系统中的定义不一样。

参考资料

文章来源: blog.csdn.net,作者:hinzer,版权归原作者所有,如需转载,请联系作者。

原文链接:blog.csdn.net/feit2417/article/details/105549384

【版权声明】本文为华为云社区用户转载文章,如果您发现本社区中有涉嫌抄袭的内容,欢迎发送邮件进行举报,并提供相关证据,一经查实,本社区将立刻删除涉嫌侵权内容,举报邮箱: cloudbbs@huaweicloud.com
  • 点赞
  • 收藏
  • 关注作者

评论(0

0/1000
抱歉,系统识别当前为高风险访问,暂不支持该操作

全部回复

上滑加载中

设置昵称

在此一键设置昵称,即可参与社区互动!

*长度不超过10个汉字或20个英文字符,设置后3个月内不可修改。

*长度不超过10个汉字或20个英文字符,设置后3个月内不可修改。