【发布时间】:2015-05-04 10:22:34
【问题描述】:
上下文:
我真的不明白内核如何在运行代码超出其时间片时保存它的状态。
我无法想象实际发生了什么。
问题:
1) 当前运行的代码(及其堆栈?)存储在哪里?
2) 当内核将再次“看到”代码时,它是否会跟随一个偏移量并继续运行,就好像什么都没发生一样?
我不清楚。
谢谢
【问题讨论】:
标签: process linux-kernel stack kernel scheduler
我真的不明白内核如何在运行代码超出其时间片时保存它的状态。
我无法想象实际发生了什么。
1) 当前运行的代码(及其堆栈?)存储在哪里?
2) 当内核将再次“看到”代码时,它是否会跟随一个偏移量并继续运行,就好像什么都没发生一样?
我不清楚。
谢谢
【问题讨论】:
标签: process linux-kernel stack kernel scheduler
这取决于操作系统,但作为一般规则,有一个存储块保存有关每个进程的信息(通常称为进程控制块或 PCB)。该信息包括指向当前正在执行的代码行的指针和寄存器的内容等,因此进程可以从上次停止的地方重新开始。
此信息块归操作系统本身而非进程所有,因此它在进程暂停后仍存在。
程序代码本身并不存储在 PCB 中 - 它只是存在于内存或磁盘中。它甚至可以在进程之间共享,例如,多个进程可能正在运行同一个程序,每个进程在任何给定时间都位于代码中的不同点,并且每个进程都有自己的一组“变量”或该进程运行所独有的数据程序。操作系统所需要的只是变量和行号或指针,以了解暂停时特定进程在代码中的位置,并且可以再次从该点开始。
值得注意的是,进程正在使用的任何 RAM 在重新启动时可能仍然存在,也可能不存在。一般来说,如果可能,操作系统会尝试将最近使用或经常使用的 RAM 块(或“页面”)留在内存中。然而,如果它需要释放空间,它可能会将“页面”换出到磁盘,但磁盘访问速度要慢得多,因此希望避免换出可能会再次使用的内存。
在最坏的情况下,操作系统可能会发现它交换了一个进程,然后很快新进程需要使用一些必须从磁盘检索的内存。它在发生这种情况时被挂起,因为在 CPU 方面检索需要很长时间。然后可能会发生下一个过程也很快发现自己处于相同的情况。操作系统现在花费大量时间来交换进程和内存,而更少的时间用于实际工作 - 这通常称为“抖动”。
【讨论】:
当前代码指令指针和当前堆栈指针存储在task_struct->ip和task_struct->sp(对于x86)和新进程的task_struct->ip和task_struct->sp中,并在@时加载回sp和ip寄存器987654321@在Linux内核中被调用。
内核的switch_to() 在切换到新进程时会执行许多操作,例如重置 EIP、堆栈、FPU、段描述符、调试寄存器。
然后内核的switch_mm()将虚拟内存映射从上一个进程切换到新进程。
【讨论】: