When is esp register set on linux?

Before the program is executed, when is the value set esp

to indicate a valid address? During a call exec

? Or in user space? I've gone through the kernel code and can't find it anywhere.

+3


source to share


1 answer


Background

x86 CPUs have two (actually four) stacks (for each task): one for user mode and one for kernel mode.

When an interrupt occurs in user mode, the CPU will set esp

to the kernel stack address (see "TSS" for more information) and push the original value esp

(user mode stack location) to the stack (kernel). eip

, cs

and are eflags

always pushed onto the stack when an interrupt occurs.

When returning from an interrupt, the command iret

will call the "old" register values ​​from the stack (kernel), and the stack pointer will point back to the user's stack.

A proactive multitasking operating system typically works like this:

Some task is in progress, which means that this task takes 100% of the CPU usage for a very short amount of time. When a timer interrupt occurs, the register values ​​for the current task are stored on the stack (CPU). The OS will be the push

values ​​of all other registers and change the value esp

to the kernel stack of another task (which were saved when another timer interrupt occurred). Then it pops

registers and executes iret

, so all registers contain the values ​​of another task, and the other task is executed.



On Linux (4.12.2), x86-32, this is done by a function __switch_to_asm

in the build source "entry_32.S".

Direct answer to your question

When creating a new task, two stacks (user and kernel) are allocated for this task, and the initial values ​​of the registers poped

in the interrupt are written to the kernel stack. This includes the initial value esp

for user mode.

Some timer interrupt later the task is started for the first time (just like the started task is activated again).

In (older versions) Linux, two commands are used to create a new task:

  • fork()

    will just copy the kernel stack. fork()

    will duplicate the existing task, so all register values ​​(including esp

    ) must be identical to the already existing task
  • execve()

    will not allocate a new kernel stack (a new task is now created, but another executable is running in the current task). Execve will allocate a new user stack and overwrite the value esp

    on the kernel stack. (Mark Carpenter's commentary shows you where this is done.)
+4


source







All Articles