这是我的猜测:
esp0 用内核栈顶地址初始化。内核栈分配时,在进程切换时用于初始化tss->esp0,以便上下文从用户态切换到内核态时,可以定位到内核栈;而esp用于保存进程切换时要调度的进程的内核栈顶。
所以 thread_struct 中的 esp0 一旦初始化就不会改变,而 esp 会改变。
我的猜测对吗?
这是我的猜测:
esp0 用内核栈顶地址初始化。内核栈分配时,在进程切换时用于初始化tss->esp0,以便上下文从用户态切换到内核态时,可以定位到内核栈;而esp用于保存进程切换时要调度的进程的内核栈顶。
所以 thread_struct 中的 esp0 一旦初始化就不会改变,而 esp 会改变。
我的猜测对吗?
该thread_struct
结构包含其中两个ESP
字段,它们是esp0
和esp
。但是,它们与结构中的四个字段相关,即、和。tss_segment_32
esp0
esp1
esp2
esp
这些实际上存在于 TSS 中,所以它很大程度上来自英特尔,而不是来自 Linus 等人的东西。
至于为什么 TSS 包含它们,如果您知道保护模型在 x86 下如何工作,这些数字是合乎逻辑的。实际上,它们是环级别(除了esp
环级别 3,尽管它实际上并没有被称为esp3
)。
换句话说,它们包含要在您正在执行的环中使用的堆栈指针。由于 Linux 仅使用环 0(内核模式)和环 3(用户模式),esp0
并且esp
是唯一需要保存的.
顺便说一句,我认为我见过的唯一使用另一个环的操作系统是 OS/2,它使用环 2 进行某些 I/O 操作。允许执行这些操作的进程必须被特别标记,并且操作系统将在 ring 2 中运行它们以允许不受限制的 I/O 访问,而不允许关闭内核。