如果我们在Linux上使用默认的调度策略创建pthread(pthread_create)或进程(fork),调度程序是否会在调度它们时将具有相同优先级的进程和线程视为同等?
假设有一个只有一个线程的进程P1和一个有两个线程T1 T2的进程P2。
假设只有一个核心... 调度是否会如下进行:
P1 T1 P1 T2 P1 T1 P1 T2
还是
P1 T1 T2 P1 T1 T2
如果我们在Linux上使用默认的调度策略创建pthread(pthread_create)或进程(fork),调度程序是否会在调度它们时将具有相同优先级的进程和线程视为同等?
假设有一个只有一个线程的进程P1和一个有两个线程T1 T2的进程P2。
假设只有一个核心... 调度是否会如下进行:
P1 T1 P1 T2 P1 T1 P1 T2
还是
P1 T1 T2 P1 T1 T2
Linux不再按进程进行调度。
在内核中,线程(thread)被调度。进程(process)的概念现在是一个人为构建的概念,主要被内核外的东西所看到。显然,内核必须知道如何将线程(thread)联系起来,但这与调度无关。
基本上,内核维护了大量的线程,每个线程都有一个线程组(group)的领导者,这就是外部看到的进程(process)。线程有一个线程ID和一个线程组ID - 这很像PID和PPID(进程ID和父进程ID)之间的关系。
当您创建一个普通的线程(thread)时,内核会为其提供全新的线程ID,但其线程组ID设置为与创建它的线程的组ID相同。这样,对外部世界而言,它看起来像是进程(process)内的线程(thread)。
当您执行fork时,内核会为其提供全新的线程ID,并将其线程组ID设置为与其线程ID相同的值。这样,对外部世界而言,它看起来像是进程(process)。
大多数非内核工具报告的进程实际上只是报告线程,其中线程ID与线程组ID相同。
其他方法有些微妙,这里可能太复杂而无法深入讨论。我上面写的是(希望)一个中等水平的论述。
现在,针对您的具体问题,既不是P1
也不是P1T2
,因为P1
只有一个线程(thread)。
在内核中,这些线程(thread)分别是P1T1
、P2T1
和P2T2
,并假设它们具有相同的调度属性和行为(a),那么它们将被安排调度。
另请参见:
更多信息请参考。
(a): 显然,这种情况会发生改变,如果线程开始在 I/O 上阻塞(内核直到 I/O 可用才调度它们),或者提前释放其时间片(内核可能会增加它们的优先级作为表现良好的奖励),但是那时它们就不再表现相同了。
确实,Linux内核(从版本2.6.23开始)调度任务,这些任务可以是线程或(单线程)进程。
除了paxdiablo的答案之外,我添加了这个答案以便提供更多关于不同线程调度方式的泛型信息。
一般来说,线程可以是用户空间线程或内核空间线程。用户空间线程通常由库实现。因此,内核几乎对它们一无所知(内核仅知道它们所属的进程),并且它们在用户空间中处理。相反,内核线程由内核实现,并且完全由内核处理。您可以从以下图像中获得泛型视图。
如您所见,左图展示了一些用户空间线程,在此情况下内核仅拥有关于进程的信息(即所谓的进程控制块-PCBs)。所有关于线程的资源信息都保存在进程内(在线程表中),并由相应的用户空间线程库处理。右图展示了内核线程,其中进程表和线程表都存储在内核中。当使用用户空间线程时,调度程序会调度进程。因此,它选择特定的进程并分配允许的时间片。然后,进程内的线程调度程序负责选择如何进行线程之间的调度。由于用户空间线程不受中断影响,所以选择的线程往往会消耗整个进程的时间片,直到完成其任务。因此,在这种情况下,假设的调度将类似于:
P1(T1), P2(T1), P1(T1), P2(T1 - T1 完成任务并 让出), P2(T2 - 剩余时间片,P1(T1), P2(T2), P1(T1), ...
当使用内核线程时,内核调度线程。内核对线程所属的进程不感兴趣,但它平等地为每个线程分配一个时间片。因此,在这种情况下,假设的调度将是:
P1(T1), P2(T1), P2(T2), P1(T1), P2(T2), P1(T1), ...