我正在研究Linux的调度程序。关于CPU核心亲和力,我想知道以下内容:
1)每个进程(线程)如何固定到核心?
有一个系统调用sched_setaffinity
来更改执行进程的核心关联。但在内部,当生成进程(或线程)时,默认的Linux调度程序如何将进程(线程)分配给特定的核心?我修改了sched_setaffinity
系统调用,以转储有关正在从一个核心移动到另一个核心的任务的信息。
printk(KERN_INFO "%d %d %ld %lu %s\n", current->pid, current->tgid,
current->state, current->cpus_allowed,
current->comm);
似乎在/var/log/messages
中没有转储上述信息。所以默认的调度程序会以不同的方式处理每个进程,但我无法弄清楚如何。
2)是否可以通过PID或其他信息获取核心ID?
这是我想在Linux内核中实现的。在task_struct
中,有一个名为cpus_allowed
的成员。但这是设置亲和力的掩码,而不是核心ID。我想检索一个数据,标识正在运行指定进程的核心。
谢谢,
答案 0 :(得分:4)
每个CPU都有自己的runqueue,AFAIK我们可以通过查找它所属的runqueue找到进程的当前CPU。给定task_struct *p
,我们可以通过struct rq = task_rq(p)
得到它的runqueue,struct rq有一个名为cpu的字段,我想这应该是答案。
我在实践中没有尝试过,只是在线阅读一些代码,并且我不太确定它是否可行。希望它可以帮到你。
答案 1 :(得分:2)
/proc/pid/stat
中的字段39告诉当前进程的核心/ cpu。
例如为:
#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上运行。
答案 2 :(得分:2)
您可以使用task_struct确定运行线程的CPU ID:
#include <linux/sched.h>
task_struct *p;
int cpu_id = task_cpu(p);
答案 3 :(得分:0)
CPU核心关联性是特定于操作系统的。操作系统知道如何执行此操作,您不必这样做。如果您指定要运行哪个核心,可能会遇到各种问题,其中一些核心实际上可能会减慢进程。
在Linux内核中,与进程task_struct关联的数据结构包含cpu_allowed位掩码字段。对于机器中的每个n个处理器,这包含n位。具有四个物理核心的机器将具有四个位。如果这些CPU核心是超线程启用的,那么它们将具有8位位掩码。如果为给定进程设置了给定位,则该进程可以在关联的核上运行。因此,如果允许进程在任何核心上运行并允许根据需要跨处理器迁移,则位掩码将完全为1秒。实际上,这是Linux下进程的默认状态。例如,
PID 2441: PRIO 0, POLICY N: SCHED_NORMAL, NICE 0, AFFINITY 0x3
进程2441的CPU亲和性为0x3,这意味着它可以在Core0和Core1中使用。
应用程序还可以通过更改位掩码使用Kernel API sched_set_affinity()指定/设置关联。