【问题标题】:How is each process pinned to a specific core by scheduler (Linux)调度程序如何将每个进程固定到特定内核(Linux)
【发布时间】:2012-03-02 03:35:37
【问题描述】:

我现在正在研究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。我想检索一个数据,该数据标识正在运行指定进程的核心。

谢谢,

【问题讨论】:

    标签: linux kernel scheduler


    【解决方案1】:

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

    我没有在实践中尝试过,只是在网上阅读了一些代码,并不太确定它是否有效。希望对您有所帮助。

    【讨论】:

    • 感谢您的回答。我试过这个方法后会告诉你的。
    • 请注意,这是不合理的 - 任务可以从一个运行队列迁移到您下方的另一个运行队列。
    【解决方案2】:

    你可以通过task_struct来确定一个线程在哪个CPU ID上运行:

    #include <linux/sched.h>
    
    task_struct *p;
    int cpu_id = task_cpu(p);
    

    【讨论】:

      【解决方案3】:

      /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 上运行。

      【讨论】:

        【解决方案4】:

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

        在 Linux Kernel 中,与进程 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 中使用。

        应用程序还可以通过更改位掩码使用内核 API sched_set_affinity() 指定/设置亲和性。

        【讨论】:

        • 感谢您的回答。但这与我想要的不同。我想知道我的描述是否具有误导性...首先,我不使用sched_setaffinity 系统调用(不是 sched_set_affinity 而是 sched_setaffinity),因为我没有创建在用户空间中运行的应用程序。
        • 其次,cpus_allowed (not cpu_allowed) 字段不足以识别进程正在运行的 CPU 内核。 cpus_allowed 默认设置为 1,以便该进程可能会移动所有可用内核。如果有任何字段/方法告诉进程运行的位置,这就是我真正想知道的。
        猜你喜欢
        • 2011-10-10
        • 2011-09-11
        • 1970-01-01
        • 2013-10-20
        • 2015-04-29
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        相关资源
        最近更新 更多