在程序执行之前, esp寄存器何时被设置为指向有效地址? 在调用exec期间? 或者在用户空间本身? 我已经通过了内核代码,似乎无法find任何地方。
如何在一个确定的地址(gcc,linux)的可执行文件中创build一个“空”空间?
通过SSH启动一个长时间运行的程序
清除串口缓冲区
Google Chrome 61.0.3163.79中的canvas在Linux上速度太慢
如何使用期望与可选的提示?
背景
x86 cpu有两个(实际上是四个)堆栈(每个任务):一个用于用户模式,一个用于内核模式。
当在用户模式下发生中断时,cpu将把esp设置为内核堆栈的地址(参见“TSS”以获取更多信息),并将esp (用户模式堆栈的位置)的原始值推送到(内核)堆栈。 当发生中断时, eip , cs和eflags总是被压入堆栈。
从中断返回时, iret指令将从(内核)堆栈弹出“旧”寄存器值,并且堆栈指针将再次指向用户的堆栈。
抢先式多任务操作系统通常以下列方式工作:
一些任务正在运行,这意味着这个任务在很短的时间内就会占用100%的cpu负载。 发生定时器中断时,当前正在运行的任务的寄存器值将被存储在堆栈中(由cpu)。 操作系统push所有其他寄存器的值,并将esp值更改为另一个任务的内核堆栈(在另一个定时器中断发生时保存)。 然后它pops寄存器并执行一个iret ,所有寄存器包含另一个任务的值,另一个任务正在运行。
在Linux(4.12.2)中,x86-32由组件源“entry_32.S”中的__switch_to_asm函数完成。
直接回答你的问题
当一个新的任务被创建时,两个堆栈(用户和内核堆栈)被分配给该任务,并且在中断中被初始化的注册值被写入内核堆栈。 这包括用户模式的esp的初始值。
有些计时器会在第一次启动任务之后中断(与已经运行的任务重新启动的方式相同)。
在(旧版本的)Linux中,有两个命令用于创建新的任务:
fork()将简单地复制内核堆栈。 fork()会复制一个已经存在的任务,所以所有的寄存器值(包括esp )必须与已经存在的任务完全相同
execve()将不会分配一个新的内核堆栈(现在新的任务被创建,但另一个可执行文件正在当前任务中运行)。 execve将分配一个新的用户堆栈并覆盖内核堆栈上的esp值。 (Mark Plotnick的评论向你展示了完成这个任务的位置。)
版权声明:本文内容由互联网用户自发贡献,该文观点与技术仅代表作者本人。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如发现本站有涉嫌侵权/违法违规的内容, 请发送邮件至 [email protected] 举报,一经查实,本站将立刻删除。