在linux中何时设置esp寄存器?
在执行程序之前,在linux中何时设置esp寄存器?,linux,Linux,在执行程序之前,esp寄存器何时设置为指向有效地址?调用exec?还是在用户空间本身?我已经浏览了内核代码,但似乎在任何地方都找不到它。Background x86 CPU有两个(实际上是四个)堆栈(每个任务):一个用于用户模式,一个用于内核模式 当在用户模式下发生中断时,CPU将esp设置为内核堆栈的地址(有关更多信息,请参阅“TSS”),并将esp(用户模式堆栈的位置)的原始值推送到(内核)堆栈eip、cs和eflags总是被推送到堆栈中 从中断返回时,iret指令将从(内核的)堆栈弹出“旧
esp
寄存器何时设置为指向有效地址?调用exec
?还是在用户空间本身?我已经浏览了内核代码,但似乎在任何地方都找不到它。Background
x86 CPU有两个(实际上是四个)堆栈(每个任务):一个用于用户模式,一个用于内核模式
当在用户模式下发生中断时,CPU将esp
设置为内核堆栈的地址(有关更多信息,请参阅“TSS”),并将esp
(用户模式堆栈的位置)的原始值推送到(内核)堆栈<当中断发生时,代码>eip、cs
和eflags
总是被推送到堆栈中
从中断返回时,iret
指令将从(内核的)堆栈弹出“旧”寄存器值,堆栈指针将再次指向用户的堆栈
抢占式多任务操作系统通常以以下方式工作:
某些任务正在运行,这意味着此任务在很短的时间内占用100%的CPU负载。当计时器中断发生时,当前运行任务的寄存器值存储在堆栈上(由CPU)。操作系统将推送
所有其他寄存器的值,并将esp
值更改为另一个任务的内核堆栈(当另一个计时器中断发生时保存)。然后它pops
寄存器并执行iret
,这样所有寄存器都包含另一个任务的值,而另一个任务正在运行
在Linux(4.12.2)x86-32中,这是通过程序集源代码“entry_32.S”中的函数\u切换到\u asm
完成的
直接回答您的问题
创建新任务时,将为该任务分配两个堆栈(用户堆栈和内核堆栈),并将中断中要poped
的初始寄存器值写入内核堆栈。这包括用户模式的esp
初始值
某些计时器会在任务第一次启动后中断(与重新激活已运行任务的方式相同)
在(旧版本的)Linux中,有两个命令用于创建新任务:
将简单地复制内核堆栈fork()
将复制现有任务,因此所有寄存器值(包括fork()
)必须与现有任务相同esp
不会分配新的内核堆栈(现在创建了新任务,但当前任务中正在运行另一个可执行文件)。Execve将分配一个新的用户堆栈,并覆盖内核堆栈上的execve()
值。(Mark Plotnick的评论向您展示了执行此操作的位置。)esp