Warning: file_get_contents(/data/phpspider/zhask/data//catemap/1/dart/3.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
在linux中何时设置esp寄存器?_Linux - Fatal编程技术网

在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将分配一个新的用户堆栈,并覆盖内核堆栈上的
    esp
    值。(Mark Plotnick的评论向您展示了执行此操作的位置。)