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