You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

Linux内核如何在多核间迁移进程?亲和性修改后涉及哪些内核函数?

Linux内核进程跨核心迁移相关问题解答

1. Linux内核如何在多个核心之间迁移进程?

咱们先从整体逻辑拆解,进程跨核心迁移是内核调度子系统的核心能力之一,主要围绕触发时机、迁移流程、约束条件这几个维度展开:

  • 触发迁移的常见场景

    • 负载均衡:内核会定期(比如通过时钟中断触发的sched_tick)检查各CPU的负载情况,如果某几个核心负载差异过大,调度器会启动负载均衡逻辑(比如sched_balance_domain),把进程从高负载核心迁移到低负载核心。
    • 主动设置亲和性:用户态通过sched_setaffinity()或者taskset工具指定进程只能在某些核心运行,触发主动迁移。
    • CPU离线:当某个核心被标记为离线时,该核心上的所有进程都会被迁移到其他可用核心。
    • 进程创建:fork出的子进程可能会被调度器分散到其他空闲核心,避免单核心过载。
  • 核心迁移流程
    不管是哪种触发场景,内核的迁移逻辑都遵循这几步:

    1. 锁定进程的task_struct和原CPU的运行队列(runqueue),防止并发修改。
    2. 如果进程处于运行状态(TASK_RUNNING),内核会给原核心发送IPI(跨处理器中断),让原核心暂停该进程并保存上下文;如果是休眠状态(比如TASK_INTERRUPTIBLE),直接跳过这一步。
    3. 将进程从原核心的runqueue中移除,更新进程的CPU亲和性掩码(cpus_allowed)。
    4. 将进程添加到目标核心的runqueue中,更新进程task_struct里的cpu字段,标记为目标核心。
    5. 如果目标核心处于空闲状态,内核会触发目标核心的调度器,让进程尽快得到执行;否则进程会在目标核心的runqueue中等待调度。
  • 关键约束

    • 必须遵守进程的CPU亲和性限制:不能把进程迁移到不在它cpus_allowed掩码里的核心。
    • 实时进程的优先级更高,迁移逻辑会优先保证实时进程的调度延迟,不会轻易迁移正在运行的实时进程(除非必要)。

2. 当Process-1调用sched_setaffinity()迁移到core-1时,哪些内核函数负责这个过程?

咱们顺着系统调用的调用链一步步看,这个场景下的核心函数路径是:

  1. 用户态到内核态的入口:用户态调用sched_setaffinity()后,会触发对应的系统调用,在x86_64架构下是__x64_sys_sched_setaffinity()(旧版本是sys_sched_setaffinity())。这个函数主要做参数校验:检查传入的PID是否合法,亲和性掩码是否有效(比如不能包含不存在的核心)。

  2. 核心参数处理:调用内核态的sched_setaffinity()函数(注意和用户态同名),它会通过PID找到目标进程的task_struct,然后调用set_cpus_allowed_ptr()来更新进程的CPU亲和性掩码。

  3. 亲和性更新与迁移触发:set_cpus_allowed_ptr()是核心函数,它会先验证新的亲和性掩码是否符合规则(比如不能是空掩码),然后判断当前进程所在的核心是否不在新掩码里,如果是,就调用migrate_task_to_cpu()执行实际迁移。

  4. 实际迁移操作:migrate_task_to_cpu()是迁移的执行者:

    • 首先检查进程是否在原核心的runqueue中,如果是,就把它移除。
    • 如果进程正在原核心上运行,发送IPI中断给原核心,让原核心暂停进程并保存上下文。
    • 调用__migrate_task()底层函数,更新进程task_struct的cpu字段为目标核心,将进程添加到目标核心的runqueue中。
    • 如果目标核心空闲,触发目标核心的调度器,让进程尽快运行。
  5. 收尾工作:迁移完成后,解锁之前锁定的task_struct和runqueue,返回结果给用户态。


内容的提问来源于stack exchange,提问作者S.Wan

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.05.22 08:46:54