我对调度线程有疑问。一方面,我了解到线程被安排并被视为Linux中的进程,这意味着它们可以像使用传统方法的任何其他进程一样进行调度。 (例如,linux中的Completely Fair Scheduler)
另一方面,我也知道CPU也可能使用Switch on Event或Fine-grain等方法在线程之间切换。例如,在高速缓存未命中事件上,CPU切换线程。但是如果调度程序不想切换线程怎么办?他们如何就一个行动达成一致?
我真的很困惑两者:谁安排一个线程?操作系统还是CPU?
非常感谢:)。
答案 0 :(得分:7)
答案是两者。
真正的相当简单:在每个核心支持多个线程的CPU上(例如,具有超线程的Intel),CPU在操作系统中看起来具有一定数量的虚拟核心。例如,英特尔i7有4个实际内核,但看起来像8个内核的操作系统。
操作系统将8个线程安排到这8个(虚拟)内核上。当需要进行任务切换时,操作系统的调度程序会查看线程并查找最有资格运行的8(考虑到线程优先级,自上次运行以来的时间等)
CPU只有4个真实核心,但这些核心支持同时执行多个指令(并且在没有依赖性的情况下乱序)。传入的指令被解码并抛入“池”。每个时钟周期,CPU都会尝试在该池中找到一些不依赖于某些先前指令结果的指令。
每个核心有多个线程,基本上每个实际核心都有两个输入流放入可能能够在给定时钟周期内执行的“池”指令中。在每个时钟周期,它仍然会查找来自该池的指令,这些指令不依赖于尚未执行的先前指令的结果。如果找到了一些,它会将它们放入执行单元并执行它们。唯一的主要变化是每条指令现在需要附加某种标记来指定哪个“虚拟核心”将用于存储结果 - 也就是说,两个线程中的每一个都有(例如)它自己的一组寄存器,并且每个线程的指令必须写入该虚拟核心的寄存器。
然而,CPU可能支持某种程度的线程优先级,以便(例如)可用指令池包含来自两个输入线程的一些指令(或者所有N个输入线程,如果有超过2)在任何给定的时钟周期中,它更愿意从一个线程中选择来自另一个线程的指令。这可以是绝对的,因此它尽可能快地运行线程A,并且线程B仅与周期A不能使用,或者它可以是“较温和”的偏好,例如尝试保持执行的指令的2:1比率(或者,当然,基本上任何其他比例都是优先的。)
当然,还有其他方法可以设置优先级(例如分区执行资源),但总体思路保持不变。
知道这样的共享内核的操作系统也可以修改其调度以适应,例如,如果该线程具有更高的优先级,则只调度一对内核上的一个线程。
答案 1 :(得分:0)
操作系统处理就绪线程(需要CPU的线程)到内核的调度和调度,以与管理其他资源类似的方式管理CPU执行。缓存未命中是没有理由交换线程。页面错误,其中所需的页面根本没有加载到RAM中,可能导致线程被阻塞,直到页面从磁盘加载。内存管理硬件通过为处理页面错误的OS驱动程序生成硬件中断来实现这一点。