关于内核:调度程序如何将每个进程固定到特定的核心(Linux)

How is each process pinned to a specific core by scheduler (Linux)

我现在正在研究Linux的调度程序。关于CPU核心亲和力,我想知道以下内容:

1)每个进程(线程)如何固定到核心?

有一个系统调用sched_setaffinity来更改执行进程的核心关联。但在内部,当生成进程(或线程)时,默认的Linux调度程序如何将进程(线程)分配给特定的核心?我修改了sched_setaffinity系统调用,以转储有关从一个核心移动到另一个核心的任务的信息。

1
2
3
4
printk(KERN_INFO"%d %d %ld %lu %s
", current->pid, current->tgid,
                                       current->state, current->cpus_allowed,
                                       current->comm);

似乎在/var/log/messages中没有转储上述信息。因此默认的调度程序以不同的方式将每个进程固定,但我无法弄清楚如何。

2)是否可以通过PID或其他信息获取核心ID?

这是我想在Linux内核中实现的。在task_struct中,有一个名为cpus_allowed的成员。但这是设置亲和力的掩码,而不是核心ID。我想检索一个数据,标识运行指定进程的核心。

谢谢,


每个CPU都有自己的runqueue,AFAIK我们可以通过查找它所属的runqueue找到进程的当前CPU。给定task_struct *p,我们可以通过struct rq = task_rq(p)得到它的runqueue,而struct rq有一个名为cpu的字段,我想这应该是答案。

我在实践中没有尝试过这个,只是在线阅读一些代码,并且我不太确定它是否可行。希望它可以帮到你。


您可以使用其task_struct确定运行线程的CPU ID:

1
2
3
4
#include <linux/sched.h>

task_struct *p;
int cpu_id = task_cpu(p);


/proc/pid/stat中的字段39告诉进程的当前核心/ cpu。

例如。:

1
2
#cat /proc/6128/stat
6128 (perl) S 3390 6128 3390 34821 6128 4202496 2317 268 0 0 1621 59 0 0 16 0 1 0 6860821 10387456 1946 18446744073709551615 1 1 0 0 0 0 0 128 0 18446744073709551615 0 0 17 8 0 0 0

过程6128在核心8上运行。


CPU核心关联性是特定于操作系统操作系统知道如何执行此操作,您不必这样做。如果您指定要运行哪个核心,可能会遇到各种问题,其中一些核心实际上可能会减慢进程。

在Linux内核中,与进程task_struct关联的数据结构包含cpu_allowed位掩码字段。对于机器中的每个n个处理器,这包含n位。具有四个物理核心的机器将具有四个位。如果这些CPU核心是超线程启用的,那么它们将具有8位位掩码。如果为给定进程设置了给定位,则该进程可以在关联的核上运行。因此,如果允许进程在任何核心上运行并允许根据需要跨处理器迁移,则位掩码将完全为1秒。实际上,这是Linux下进程的默认状态。例如,

1
PID  2441: PRIO 0, POLICY N: SCHED_NORMAL, NICE 0, AFFINITY 0x3

进程2441具有0x3的CPU亲和性,这意味着它可以在Core0和Core1中使用。

应用程序还可以通过更改位掩码使用Kernel API sched_set_affinity()指定/设置关联。