何时在linux中设置esp寄存器?

时间:2017-07-16 15:19:18

标签: linux

在程序执行之前,esp寄存器何时设置为指向有效地址?在致电exec期间?还是在用户空间本身?我已经完成了内核代码,似乎无法在任何地方找到它。

1 个答案:

答案 0 :(得分:4)

<强>背景

x86 CPU有两个(实际上是四个)堆栈(每个任务):一个用于用户模式,一个用于内核模式。

当用户模式发生中断时,CPU会将esp设置为内核堆栈的地址(有关详细信息,请参阅“TSS”)并推送esp的原始值(位置用户模式的堆栈)到(内核)堆栈。发生中断时,eipcseflags总是被推入堆栈。

从中断返回时,iret指令将从(内核)堆栈中弹出“旧”寄存器值,堆栈指针将再次指向用户的堆栈。

抢先式多任务操作系统通常以下列方式工作:

某些任务正在运行,这意味着此任务在很短的时间内占用100%的CPU负载。当发生定时器中断时,当前运行的任务的寄存器值存储在堆栈中(由CPU)。操作系统将push所有其他寄存器的值,并将esp值更改为另一个任务的内核堆栈(在发生另一个定时器中断时保存)。然后它pops寄存器并执行iret所以所有寄存器都包含另一个任务的值,另一个任务正在运行。

在Linux(4.12.2)中,x86-32这是由汇编源“entry_32.S”中的函数__switch_to_asm完成的。

直接回答您的问题

当创建新任务时,为该任务分配两个堆栈(用户和内核堆栈),并将中断中的初始寄存器值poped写入内核堆栈。这包括用户模式的初始值esp

某些计时器中断后,第一次启动任务(与重新激活已经运行的任务的方式相同)。

在(旧版本)Linux中,有两个用于创建新任务的命令:

  • fork()将简单地复制内核堆栈。 fork()将复制现有任务,因此所有注册值(包括esp)必须与现有任务相同
  • execve()将不会分配新的内核堆栈(现在已创建新任务,但正在当前任务中运行另一个可执行文件)。 Execve将分配一个新的用户堆栈并覆盖内核堆栈上的esp值。 (Mark Plotnick的评论向您展示了这样做的位置。)