task:

  • task 保存了内核栈的地址
  • Linux 给每个 task 都分配了内核栈
  1. struct thread_info thread_info;
  2. void *stack;

用户态函数栈

image.png

  • 被调用函数栈保存了调用者的栈基址
  • 以上的栈操作,都是在进程的内存空间里面进行的

内核态函数栈

内核栈是一个非常特殊的结构,如下图所示:

image.png

  • 与体系结构有关的,都放在 thread_info 里面
  • 在内核中,CPU 的寄存器 ESP 或者 RSP,已经指向内核栈的栈顶,在内核态里的调用都有和用户态相似的过程。

从上面的过程来看, 如果当前是用户态的代码, 在进行各种函数调用时, 栈会不断的增长. 而切到内核态时, 并不是继续在当前栈增长, 而是跳到了另一个栈, 也就是内核栈中执行.

当系统调用从用户态到内核态的时候,首先要做的第一件事情,就是将用户态运行过程中的 CPU 上下文保存起来,其实主要就是保存在这个结构的寄存器变量里。这样当从内核系统调用返回的时候,才能让进程在刚才的地方接着运行下去。

通过 task_struct 找内核栈

通过内核栈找 task_struct

总结

image.png