第一部分:源码目录树形分析

1.1 编译前源码结构(开发者视角)

这是开发者通过git clone或下载源码包后,在构建主机上看到的目录树。

linux-6.1/                                    # 内核源码根目录(编译前)
│
├── arch/                                      # 架构相关代码
│   ├── arm64/                                 # ARM64架构
│   │   ├── kernel/
│   │   │   ├── smp.c                          # ARM64 SMP初始化
│   │   │   ├── smp_spin_table.c               # 自旋表启动方式
│   │   │   ├── smp_psci.c                     # PSCI固件启动
│   │   │   ├── head.S                         # 内核入口汇编
│   │   │   ├── process.c                      # 进程切换
│   │   │   └── setup.c                        # 架构初始化
│   │   ├── mm/
│   │   │   ├── init.c                         # ARM64内存初始化
│   │   │   ├── fault.c                        # 缺页异常
│   │   │   └── cache.S                        # 缓存操作
│   │   ├── include/asm/
│   │   │   ├── smp.h                          # 架构SMP头文件
│   │   │   ├── atomic.h                       # 原子操作
│   │   │   ├── spinlock.h                     # 自旋锁
│   │   │   └── mmu.h                          # MMU相关
│   │   ├── Kconfig                            # ARM64配置选项
│   │   └── Makefile
│   ├── x86/                                   # x86架构(对比参考)
│   │   └── kernel/smp.c
│   └── Kconfig                                # 顶层架构选择
│
├── kernel/                                    # 核心子系统
│   ├── sched/                                 # 调度器
│   │   ├── core.c                             # 核心调度逻辑(__schedule)
│   │   ├── fair.c                             # CFS完全公平调度类
│   │   ├── rt.c                               # 实时调度类
│   │   ├── deadline.c                         # 限期调度类
│   │   ├── idle.c                             # 空闲调度类
│   │   ├── stop_task.c                        # 停止任务调度类
│   │   ├── topology.c                         # 调度域拓扑
│   │   ├── loadavg.c                          # 负载计算
│   │   ├── cpupri.c                           # CPU优先级管理
│   │   ├── cpudeadline.c                      # CPU限期管理
│   │   ├── smp.h                              # 调度内部SMP接口
│   │   ├── stats.c                            # 调度统计
│   │   └── debug.c                            # 调度调试
│   ├── smp.c                                  # 通用SMP函数
│   │   ├── smp_call_function_single()         # 单CPU函数调用
│   │   ├── smp_call_function_many()           # 多CPU函数调用
│   │   ├── on_each_cpu()                      # 每个CPU执行
│   │   └── flush_smp_call_function_queue()    # IPI队列处理
│   ├── softirq.c                              # 软中断
│   ├── stop_machine.c                         # 停止所有CPU
│   ├── cpu.c                                  # CPU热插拔
│   ├── irq/
│   │   ├── irqdesc.c                          # 中断描述符
│   │   ├── manage.c                           # 中断管理
│   │   └── affinity.c                         # 中断亲和性
│   ├── fork.c                                 # 进程创建(copy_process)
│   ├── exit.c                                 # 进程退出
│   └── sched/
│       └── core.c
│
├── mm/                                        # 内存管理
│   ├── page_alloc.c                           # 页分配器
│   ├── slub.c                                 # SLUB分配器
│   ├── vmalloc.c                              # 虚拟内存分配
│   ├── memory.c                               # 内存管理核心
│   └── hugetlb.c                              # 大页管理
│
├── include/                                   # 内核头文件
│   ├── linux/
│   │   ├── smp.h                              # SMP API定义
│   │   │   ├── get_cpu()/put_cpu()
│   │   │   ├── smp_processor_id()
│   │   │   ├── on_each_cpu()
│   │   │   └── smp_call_function()
│   │   ├── sched.h                            # 调度器头文件
│   │   │   ├── task_struct                    # 进程描述符
│   │   │   ├── sched_class                    # 调度类结构
│   │   │   └── rq                             # 运行队列
│   │   ├── percpu.h                           # per-CPU变量
│   │   ├── cpus.h                             # CPU掩码操作
│   │   ├── atomic.h                           # 原子操作
│   │   └── spinlock.h                         # 自旋锁
│   └── asm/                                   # 架构头文件(链接到arch/arm64/include/asm)
│       └── smp.h
│
├── init/                                      # 内核初始化
│   ├── main.c                                 # start_kernel()入口
│   └── Kconfig                                # CONFIG_SMP配置
│
├── drivers/                                   # 设备驱动
│   ├── base/
│   │   └── cpu.c                              # CPU设备模型
│   ├── irqchip/                               # 中断控制器驱动
│   │   └── irq-gic-v3.c                       # GICv3驱动
│   └── net/                                   # 网络驱动
│       └── dev.c
│
├── fs/                                        # 文件系统
│   ├── ext4/                                  # ext4文件系统
│   ├── fat/                                   # FAT文件系统
│   └── proc/                                  # proc文件系统
│       └── stat.c                             # /proc/stat
│
├── lib/                                       # 通用库函数
│   ├── smp_processor_id.c                     # smp_processor_id()调试
│   └── locking/                               # 锁实现
│
├── scripts/                                   # 配置/编译脚本
│   ├── kconfig/                               # Kconfig解析
│   └── Makefile.*                             # 编译规则
│
├── tools/                                     # 用户态工具
│   ├── perf/                                  # perf性能分析工具
│   └── trace/                                 # 追踪工具
│
├── Documentation/                             # 内核文档
│   ├── scheduler/sched-domains.txt            # 调度域文档
│   └── core-api/smp_processor_id.rst
│
├── virt/                                      # 虚拟化
│   └── kvm/                                   # KVM虚拟化
│       └── arm64/                             # ARM64 KVM支持
│
├── Kconfig                                    # 顶层配置菜单
├── Makefile                                   # 顶层Makefile
└── README                                     # 说明文件

1.2 运行时系统结构(目标机视角)

这是内核编译安装后,在ARM64目标系统(如树莓派、RK3588开发板)上看到的目录结构。

/                                             # 根文件系统
│
├── boot/                                      # 内核启动文件
│   ├── vmlinuz-6.1.0-arm64                   # 压缩内核镜像
│   ├── System.map-6.1.0-arm64                # 内核符号表(地址→函数名)
│   ├── config-6.1.0-arm64                    # 内核编译配置
│   └── dtbs/                                 # 设备树二进制文件
│       └── rockchip/
│           └── rk3588-evb.dtb
│
├── lib/                                       # 库文件
│   └── modules/                              # 内核模块目录
│       └── 6.1.0-arm64/                      # 每个内核版本一个子目录
│           ├── kernel/                       # .ko模块文件
│           │   ├── drivers/
│           │   │   ├── mmc/                  # MMC驱动模块
│           │   │   ├── net/                  # 网卡驱动模块
│           │   │   └── usb/                  # USB驱动模块
│           │   ├── fs/
│           │   │   ├── ext4.ko
│           │   │   └── vfat.ko
│           │   └── net/
│           │       └── ipv6.ko
│           ├── modules.dep                   # 模块依赖关系
│           ├── modules.alias                 # 模块别名
│           ├── modules.symbols               # 模块符号表
│           └── build/                        # 符号链接 → 源码目录
│
├── usr/                                       # 用户程序
│   └── src/                                  # 源码目录(可选)
│       └── linux-6.1.0/                      # 通常不存在,需手动安装
│
├── proc/                                      # proc文件系统(内核接口)
│   ├── cpuinfo                               # CPU信息
│   ├── stat                                  # 系统统计
│   ├── interrupts                            # 中断分布
│   ├── softirqs                              # 软中断统计
│   ├── schedstat                             # 调度器统计
│   ├── [pid]/                                # 每个进程目录
│   │   ├── stat                              # 进程状态
│   │   └── task/                             # 线程信息
│   └── self/
│       └── task/
│
├── sys/                                       # sysfs文件系统
│   └── devices/
│       └── system/
│           └── cpu/                          # CPU设备信息
│               ├── cpu0/                     # CPU0设备目录
│               ├── cpu1/
│               ├── present                   # 在线CPU掩码
│               ├── possible                  # 可能CPU掩码
│               ├── offline                   # 离线CPU
│               └── kernel_max                # 最大CPU编号
│
├── dev/                                       # 设备文件
│   ├── mmcblk0/                              # eMMC块设备
│   └── ttyS0/                                # 串口设备
│
└── etc/                                       # 配置文件
    └── modprobe.d/                           # 模块配置

1.3 关键文件依赖关系图

                    ┌─────────────────────────────────────────┐
                    │  编译前: arch/arm64/kernel/head.S       │
                    │          _text (入口点)                 │
                    └───────────────────┬─────────────────────┘
                                        │
                                        ▼
                    ┌─────────────────────────────────────────┐
                    │  init/main.c                            │
                    │  start_kernel()                         │
                    └───────────────────┬─────────────────────┘
                                        │
            ┌───────────────────────────┼───────────────────────────┐
            │                           │                           │
            ▼                           ▼                           ▼
┌───────────────────────┐   ┌───────────────────────┐   ┌───────────────────────┐
│ arch/arm64/kernel/    │   │ kernel/sched/core.c   │   │ mm/page_alloc.c       │
│ smp.c                 │   │ scheduler_tick()      │   │ 内存初始化            │
│ smp_init_cpus()       │   │                       │   │                       │
└───────────┬───────────┘   └───────────┬───────────┘   └───────────────────────┘
            │                           │
            ▼                           ▼
┌───────────────────────┐   ┌───────────────────────┐
│ arch/arm64/kernel/    │   │ kernel/sched/fair.c   │
│ smp_spin_table.c      │   │ trigger_load_balance()│
│ smp_psci.c            │   │                       │
└───────────┬───────────┘   └───────────┬───────────┘
            │                           │
            ▼                           ▼
┌───────────────────────┐   ┌───────────────────────┐
│ kernel/smp.c          │   │ kernel/sched/core.c   │
│ smp_call_function_*() │   │ pick_next_task()      │
└───────────────────────┘   └───────────────────────┘

第二部分:数据结构树形分析

2.1 核心数据结构层次图

┌─────────────────────────────────────────────────────────────────────────────────────┐
│                              SMP 核心数据结构                                        │
├─────────────────────────────────────────────────────────────────────────────────────┤
│                                                                                      │
│  ┌────────────────────────────────────────────────────────────────────────────────┐ │
│  │  struct task_struct (include/linux/sched.h)                                   │ │
│  │  ┌──────────────────────────────────────────────────────────────────────────┐ │ │
│  │  │  进程描述符(每个任务一个)                                              │ │ │
│  │  ├──────────────────────────────────────────────────────────────────────────┤ │ │
│  │  │  volatile long state;              // 进程状态 (TASK_RUNNING等)          │ │ │
│  │  │  int prio, static_prio, normal_prio;  // 优先级 (0-139)                  │ │ │
│  │  │  unsigned int policy;              // 调度策略 (SCHED_NORMAL等)          │ │ │
│  │  │  struct sched_class *sched_class;  // 调度类指针                         │ │ │
│  │  │  struct sched_entity se;           // CFS调度实体                        │ │ │
│  │  │  struct sched_rt_entity rt;        // RT调度实体                         │ │ │
│  │  │  struct sched_dl_entity dl;        // DL调度实体                         │ │ │
│  │  │  int cpu;                          // 当前运行的CPU                      │ │ │
│  │  │  int on_cpu;                       // 是否正在CPU上运行                  │ │ │
│  │  │  int on_rq;                        // 是否在运行队列中                   │ │ │
│  │  │  cpumask_t cpus_allowed;           // CPU亲和性掩码                      │ │ │
│  │  │  unsigned int migration_disabled;  // 迁移禁用标志                       │ │ │
│  │  │  struct list_head tasks;           // 全局任务链表                       │ │ │
│  │  └──────────────────────────────────────────────────────────────────────────┘ │ │
│  └────────────────────────────────────────────────────────────────────────────────┘ │
│                                                                                      │
│  ┌────────────────────────────────────────────────────────────────────────────────┐ │
│  │  struct rq (kernel/sched/sched.h)                                             │ │
│  │  ┌──────────────────────────────────────────────────────────────────────────┐ │ │
│  │  │  运行队列(per-CPU变量)                                                 │ │ │
│  │  ├──────────────────────────────────────────────────────────────────────────┤ │ │
│  │  │  unsigned int nr_running;        // 运行队列中的任务数                   │ │ │
│  │  │  struct cfs_rq cfs;              // CFS运行队列                          │ │ │
│  │  │  struct rt_rq rt;                // RT运行队列                           │ │ │
│  │  │  struct dl_rq dl;                // DL运行队列                           │ │ │
│  │  │  struct task_struct *curr;       // 当前运行的任务                       │ │ │
│  │  │  struct task_struct *idle;       // 空闲任务                             │ │ │
│  │  │  int cpu;                        // 所属CPU                              │ │ │
│  │  │  int online;                     // CPU是否在线                          │ │ │
│  │  │  #ifdef CONFIG_SMP                                                       │ │ │
│  │  │    struct sched_domain *sd;      // 调度域                               │ │ │
│  │  │    int active_balance;           // 主动均衡标志                         │ │ │
│  │  │    int push_cpu;                 // 推送目标CPU                          │ │ │
│  │  │    struct task_struct *migration_thread; // 迁移线程                     │ │ │
│  │  │    struct list_head migration_queue;     // 迁移请求队列                 │ │ │
│  │  │    u64 nr_switches;              // 上下文切换次数                       │ │ │
│  │  │    u64 nr_load_updates;          // 负载更新次数                         │ │ │
│  │  │    raw_spinlock_t lock;          // 队列锁                               │ │ │
│  │  │  #endif                                                                │ │ │
│  │  └──────────────────────────────────────────────────────────────────────────┘ │ │
│  └────────────────────────────────────────────────────────────────────────────────┘ │
│                                                                                      │
│  ┌────────────────────────────────────────────────────────────────────────────────┐ │
│  │  struct sched_class (kernel/sched/sched.h)                                    │ │
│  │  ┌──────────────────────────────────────────────────────────────────────────┐ │ │
│  │  │  调度类(多态调度,链表组织)                                            │ │ │
│  │  ├──────────────────────────────────────────────────────────────────────────┤ │ │
│  │  │  void (*enqueue_task)(struct rq *rq, struct task_struct *p);            │ │ │
│  │  │  void (*dequeue_task)(struct rq *rq, struct task_struct *p);            │ │ │
│  │  │  void (*yield_task)(struct rq *rq);                                     │ │ │
│  │  │  void (*check_preempt_curr)(struct rq *rq, struct task_struct *p);      │ │ │
│  │  │  struct task_struct *(*pick_next_task)(struct rq *rq);                  │ │ │
│  │  │  void (*task_tick)(struct rq *rq, struct task_struct *p, int queued);   │ │ │
│  │  │  #ifdef CONFIG_SMP                                                       │ │ │
│  │  │    unsigned long (*load_balance)(struct rq *this_rq, ...);             │ │ │
│  │  │    int (*move_one_task)(struct rq *this_rq, ...);                      │ │ │
│  │  │  #endif                                                                │ │ │
│  │  └──────────────────────────────────────────────────────────────────────────┘ │ │
│  └────────────────────────────────────────────────────────────────────────────────┘ │
│                                                                                      │
│  ┌────────────────────────────────────────────────────────────────────────────────┐ │
│  │  struct sched_domain (kernel/sched/sched.h)                                   │ │
│  │  ┌──────────────────────────────────────────────────────────────────────────┐ │ │
│  │  │  调度域(CPU分组,树形组织)                                             │ │ │
│  │  ├──────────────────────────────────────────────────────────────────────────┤ │ │
│  │  │  struct sched_domain *parent;    // 父域                                 │ │ │
│  │  │  struct sched_domain *child;     // 子域                                 │ │ │
│  │  │  struct sched_group *groups;     // 调度组                               │ │ │
│  │  │  cpumask_t span;                 // 包含的CPU掩码                        │ │ │
│  │  │  unsigned long min_interval;     // 最小负载均衡间隔                     │ │ │
│  │  │  unsigned long max_interval;     // 最大负载均衡间隔                     │ │ │
│  │  │  unsigned int busy_factor;       // 忙碌因子                             │ │ │
│  │  │  unsigned int imbalance_pct;     // 不平衡百分比阈值                     │ │ │
│  │  │  unsigned int cache_nice_tries;  // 缓存亲和性尝试次数                   │ │ │
│  │  └──────────────────────────────────────────────────────────────────────────┘ │ │
│  └────────────────────────────────────────────────────────────────────────────────┘ │
│                                                                                      │
│  ┌────────────────────────────────────────────────────────────────────────────────┐ │
│  │  struct smp_operations (arch/arm64/include/asm/smp.h)                         │ │
│  │  ┌──────────────────────────────────────────────────────────────────────────┐ │ │
│  │  │  SMP操作集(ARM64架构相关)                                              │ │ │
│  │  ├──────────────────────────────────────────────────────────────────────────┤ │ │
│  │  │  void (*smp_init_cpus)(void);            // 初始化CPU映射                │ │ │
│  │  │  void (*smp_prepare_cpus)(unsigned int); // 准备启动secondary CPU        │ │ │
│  │  │  void (*smp_secondary_init)(unsigned int); // secondary CPU初始化        │ │ │
│  │  │  int (*smp_boot_secondary)(unsigned int, struct task_struct*);          │ │ │
│  │  │  #ifdef CONFIG_HOTPLUG_CPU                                               │ │ │
│  │  │    int (*cpu_kill)(unsigned int);         // 关闭CPU                     │ │ │
│  │  │    void (*cpu_die)(unsigned int);                                        │ │ │
│  │  │    int (*cpu_disable)(unsigned int);                                     │ │ │
│  │  │  #endif                                                                  │ │ │
│  │  └──────────────────────────────────────────────────────────────────────────┘ │ │
│  └────────────────────────────────────────────────────────────────────────────────┘ │
│                                                                                      │
└─────────────────────────────────────────────────────────────────────────────────────┘

2.2 per-CPU变量机制

┌─────────────────────────────────────────────────────────────────────────────────────┐
│                           per-CPU 变量存储布局                                       │
├─────────────────────────────────────────────────────────────────────────────────────┤
│                                                                                      │
│  声明方式(编译前源码):                                                             │
│  ┌────────────────────────────────────────────────────────────────────────────────┐ │
│  │  DEFINE_PER_CPU(type, name);     // 定义per-CPU变量                           │ │
│  │  DECLARE_PER_CPU(type, name);     // 声明                                     │ │
│  │  get_cpu_var(name);               // 获取当前CPU的变量(禁用抢占)            │ │
│  │  put_cpu_var(name);               // 完成操作,重新启用抢占                   │ │
│  │  per_cpu(name, cpu);              // 获取指定CPU的变量                        │ │
│  │  this_cpu_ptr(name);              // 获取当前CPU指针                          │ │
│  └────────────────────────────────────────────────────────────────────────────────┘ │
│                                                                                      │
│  运行时内存布局(ARM64,NR_CPUS=4):                                                │
│                                                                                      │
│  ┌────────────────────────────────────────────────────────────────────────────────┐ │
│  │                            内核数据段                                          │ │
│  │  ┌─────────────┬─────────────┬─────────────┬─────────────┐                    │ │
│  │  │ CPU0 变量   │ CPU1 变量   │ CPU2 变量   │ CPU3 变量   │  ← per-CPU区域    │ │
│  │  │ 副本        │ 副本        │ 副本        │ 副本        │                    │ │
│  │  └─────────────┴─────────────┴─────────────┴─────────────┘                    │ │
│  │        ▲             ▲             ▲             ▲                           │ │
│  │        │             │             │             │                           │ │
│  │   ┌────┴────┐   ┌────┴────┐   ┌────┴────┐   ┌────┴────┐                       │ │
│  │   │ CPU0    │   │ CPU1    │   │ CPU2    │   │ CPU3    │                       │ │
│  │   │ 寄存器  │   │ 寄存器  │   │ 寄存器  │   │ 寄存器  │                       │ │
│  │   │ SP_EL0  │   │ SP_EL0  │   │ SP_EL0  │   │ SP_EL0  │                       │ │
│  │   └─────────┘   └─────────┘   └─────────┘   └─────────┘                       │ │
│  └────────────────────────────────────────────────────────────────────────────────┘ │
│                                                                                      │
│  典型per-CPU变量(源码中定义):                                                      │
│  ┌────────────────────────────────────────────────────────────────────────────────┐ │
│  │  DEFINE_PER_CPU(struct rq, runqueues);        // kernel/sched/core.c          │ │
│  │  DEFINE_PER_CPU(struct task_struct *, curr_task); // kernel/sched/core.c      │ │
│  │  DEFINE_PER_CPU(struct softnet_data, softnet_data); // net/core/dev.c         │ │
│  │  DEFINE_PER_CPU(struct hrtimer_cpu_base, hrtimer_bases); // kernel/time/hrtimer.c│ │
│  │  DEFINE_PER_CPU(struct tick_device, tick_cpu_device); // kernel/time/tick-common.c│ │
│  │  DEFINE_PER_CPU(struct mm_struct *, idle_mm); // arch/arm64/mm/mm.h            │ │
│  └────────────────────────────────────────────────────────────────────────────────┘ │
│                                                                                      │
└─────────────────────────────────────────────────────────────────────────────────────┘

第三部分:算法计算树形分析

3.1 负载均衡算法树

┌─────────────────────────────────────────────────────────────────────────────────────┐
│                              负载均衡算法层次图                                      │
├─────────────────────────────────────────────────────────────────────────────────────┤
│                                                                                      │
│  负载均衡触发点(运行时):                                                           │
│  ┌────────────────────────────────────────────────────────────────────────────────┐ │
│  │ 1. 周期性触发: scheduler_tick() → trigger_load_balance() → raise_softirq()   │ │
│  │ 2. 进程唤醒: try_to_wake_up() → wake_balance() → select_task_rq()            │ │
│  │ 3. 空闲均衡: idle_balance() → 空闲CPU从其他CPU拉取任务                        │ │
│  │ 4. 主动均衡: active_load_balance() → 迁移线程处理                              │ │
│  └────────────────────────────────────────────────────────────────────────────────┘ │
│                                      │                                               │
│                                      ▼                                               │
│  ┌────────────────────────────────────────────────────────────────────────────────┐ │
│  │                    负载计算:load = weight * nr_running                        │ │
│  │                                                                                │ │
│  │  weight计算(CFS,kernel/sched/sched.h):                                     │ │
│  │  ┌──────────────────────────────────────────────────────────────────────────┐ │ │
│  │  │  const int sched_prio_to_weight[40] = {                                 │ │ │
│  │  │      /* -20 */ 88761, 71755, 56483, 46273, 36291,                       │ │ │
│  │  │      /* -15 */ 29154, 23254, 18705, 14949, 11916,                       │ │ │
│  │  │      /* -10 */ 9548, 7620, 6100, 4904, 3906,                            │ │ │
│  │  │      /* -5 */ 3121, 2501, 1991, 1586, 1277,                             │ │ │
│  │  │      /* 0 */ 1024, 820, 655, 526, 423,                                  │ │ │
│  │  │      /* 5 */ 335, 272, 215, 172, 137,                                   │ │ │
│  │  │      /* 10 */ 110, 87, 70, 56, 45,                                      │ │ │
│  │  │      /* 15 */ 36, 29, 23, 18, 15                                        │ │ │
│  │  │  };                                                                      │ │ │
│  │  └──────────────────────────────────────────────────────────────────────────┘ │ │
│  └────────────────────────────────────────────────────────────────────────────────┘ │
│                                      │                                               │
│                                      ▼                                               │
│  ┌────────────────────────────────────────────────────────────────────────────────┐ │
│  │  find_busiest_queue() (kernel/sched/fair.c)                                   │ │
│  │  ┌──────────────────────────────────────────────────────────────────────────┐ │ │
│  │  │  算法:遍历调度域内所有CPU的运行队列                                     │ │ │
│  │  │  1. 跳过空闲队列 (nr_running == 0)                                      │ │ │
│  │  │  2. 计算每个队列的 load = load_avg / nr_running                         │ │ │
│  │  │  3. 找出 load 最大的队列                                                │ │ │
│  │  │  4. 检查负载差是否超过 imbalance_pct 阈值                               │ │ │
│  │  │  5. 如果超过阈值,返回该队列;否则返回NULL                              │ │ │
│  │  └──────────────────────────────────────────────────────────────────────────┘ │ │
│  └────────────────────────────────────────────────────────────────────────────────┘ │
│                                      │                                               │
│                                      ▼                                               │
│  ┌────────────────────────────────────────────────────────────────────────────────┐ │
│  │  move_tasks() (kernel/sched/fair.c)                                           │ │
│  │  ┌──────────────────────────────────────────────────────────────────────────┐ │ │
│  │  │  算法:从最忙队列迁移任务到当前队列                                      │ │ │
│  │  │                                                                          │ │ │
│  │  │  while (当前队列负荷 < 目标负荷) {                                      │ │ │
│  │  │      // 1. 选择可迁移任务                                              │ │ │
│  │  │      task = pick_next_task_from_busiest_queue();                        │ │ │
│  │  │                                                                          │ │ │
│  │  │      // 2. 检查亲和性                                                   │ │ │
│  │  │      if (!cpumask_test_cpu(this_cpu, &task->cpus_allowed))              │ │ │
│  │  │          continue;  // 不能迁移到此CPU                                  │ │ │
│  │  │                                                                          │ │ │
│  │  │      // 3. 执行迁移                                                    │ │ │
│  │  │      dequeue_task(busiest_rq, task);                                    │ │ │
│  │  │      enqueue_task(this_rq, task);                                       │ │ │
│  │  │                                                                          │ │ │
│  │  │      // 4. 更新负荷统计                                                 │ │ │
│  │  │      update_load();                                                     │ │ │
│  │  │  }                                                                       │ │ │
│  │  └──────────────────────────────────────────────────────────────────────────┘ │ │
│  └────────────────────────────────────────────────────────────────────────────────┘ │
│                                                                                      │
└─────────────────────────────────────────────────────────────────────────────────────┘

3.2 调度域层级算法(ARM64示例)

┌─────────────────────────────────────────────────────────────────────────────────────┐
│                   调度域层级(ARM64 big.LITTLE 配置)                                │
├─────────────────────────────────────────────────────────────────────────────────────┤
│                                                                                      │
│  硬件布局(如RK3588:4xA76 + 4xA55):                                               │
│  ┌────────────────────────────────────────────────────────────────────────────────┐ │
│  │                                                                                │ │
│  │   Cluster 0 (性能核)          Cluster 1 (能效核)                              │ │
│  │  ┌─────────────────────┐     ┌─────────────────────┐                          │ │
│  │  │ A76-0  A76-1        │     │ A55-0  A55-1        │                          │ │
│  │  │ A76-2  A76-3        │     │ A55-2  A55-3        │                          │ │
│  │  │      L3 Cache       │     │      L3 Cache       │                          │ │
│  │  └─────────────────────┘     └─────────────────────┘                          │ │
│  │            │                           │                                       │ │
│  │            └───────────┬───────────────┘                                       │ │
│  │                        │                                                       │ │
│  │                  DSU互联 (DynamIQ)                                            │ │
│  └────────────────────────────────────────────────────────────────────────────────┘ │
│                                                                                      │
│  调度域层级(内核构建时由arch/arm64/kernel/topology.c初始化):                      │
│  ┌────────────────────────────────────────────────────────────────────────────────┐ │
│  │                                                                                │ │
│  │  层级0: MC (Multi-Core) - 单个Cluster内                                      │ │
│  │  ┌──────────────────────────────────────────────────────────────────────────┐ │ │
│  │  │  ┌─────────────────────┐     ┌─────────────────────┐                    │ │ │
│  │  │  │  Cluster0 MC域      │     │  Cluster1 MC域      │                    │ │ │
│  │  │  │  CPU0,CPU1,CPU2,CPU3│     │  CPU4,CPU5,CPU6,CPU7│                    │ │ │
│  │  │  │  均衡: 积极         │     │  均衡: 积极         │                    │ │ │
│  │  │  └─────────────────────┘     └─────────────────────┘                    │ │ │
│  │  └──────────────────────────────────────────────────────────────────────────┘ │ │
│  │                                      │                                         │ │
│  │                                      ▼                                         │ │
│  │  层级1: DIE - 整个SoC                                                         │ │
│  │  ┌──────────────────────────────────────────────────────────────────────────┐ │ │
│  │  │  ┌─────────────────────────────────────────────────────────────────────┐ │ │
│  │  │  │  DIE域: 所有CPU (0-7)                                              │ │ │
│  │  │  │  均衡: 保守(跨Cluster迁移开销大)                                  │ │ │
│  │  │  │  阈值: imbalance_pct = 125% (允许25%不平衡)                        │ │ │
│  │  │  │  额外策略: 优先在相同Cluster内均衡                                  │ │ │
│  │  │  └─────────────────────────────────────────────────────────────────────┘ │ │
│  │  └──────────────────────────────────────────────────────────────────────────┘ │ │
│  └────────────────────────────────────────────────────────────────────────────────┘ │
│                                                                                      │
└─────────────────────────────────────────────────────────────────────────────────────┘

第四部分:数据流程文字图树形分析

4.1 进程唤醒数据流(try_to_wake_up)

┌─────────────────────────────────────────────────────────────────────────────────────┐
│                        try_to_wake_up() 数据流                                       │
├─────────────────────────────────────────────────────────────────────────────────────┤
│                                                                                      │
│  ┌────────────────────────────────────────────────────────────────────────────────┐ │
│  │  输入: task_struct *p (被唤醒的进程)                                          │ │
│  └────────────────────────────────────────────────────────────────────────────────┘ │
│                                      │                                               │
│                                      ▼                                               │
│  ┌────────────────────────────────────────────────────────────────────────────────┐ │
│  │  Step 1: 检查任务状态 (kernel/sched/core.c)                                   │ │
│  │  ┌──────────────────────────────────────────────────────────────────────────┐ │ │
│  │  │  if (task->state == TASK_RUNNING) return 1;  // 已经在运行               │ │ │
│  │  │  if (task->state & TASK_NORMAL) {                                        │ │ │
│  │  │      // 继续唤醒流程                                                    │ │ │
│  │  │  }                                                                        │ │ │
│  │  └──────────────────────────────────────────────────────────────────────────┘ │ │
│  └────────────────────────────────────────────────────────────────────────────────┘ │
│                                      │                                               │
│                                      ▼                                               │
│  ┌────────────────────────────────────────────────────────────────────────────────┐ │
│  │  Step 2: 选择目标CPU (select_task_rq)                                         │ │
│  │  ┌──────────────────────────────────────────────────────────────────────────┐ │ │
│  │  │  if (task->cpus_allowed 有限制) {                                        │ │ │
│  │  │      target_cpu = cpumask_any_and(&task->cpus_allowed, cpu_online_mask);│ │ │
│  │  │  } else {                                                                │ │ │
│  │  │      // 优先使用上次运行的CPU (缓存亲和性)                               │ │ │
│  │  │      target_cpu = task->wake_cpu;                                        │ │ │
│  │  │      // 如果上次运行的CPU负载过高,选择负载最低的CPU                     │ │ │
│  │  │      if (cpu_load(target_cpu) > threshold) {                            │ │ │
│  │  │          target_cpu = find_idlest_cpu();                                │ │ │
│  │  │      }                                                                   │ │ │
│  │  │  }                                                                        │ │ │
│  │  └──────────────────────────────────────────────────────────────────────────┘ │ │
│  └────────────────────────────────────────────────────────────────────────────────┘ │
│                                      │                                               │
│                                      ▼                                               │
│  ┌────────────────────────────────────────────────────────────────────────────────┐ │
│  │  Step 3: 获取目标CPU的运行队列锁                                               │ │
│  │  ┌──────────────────────────────────────────────────────────────────────────┐ │ │
│  │  │  rq = cpu_rq(target_cpu);                                               │ │ │
│  │  │  raw_spin_lock_irqsave(&rq->lock, flags);                               │ │ │
│  │  └──────────────────────────────────────────────────────────────────────────┘ │ │
│  └────────────────────────────────────────────────────────────────────────────────┘ │
│                                      │                                               │
│                                      ▼                                               │
│  ┌────────────────────────────────────────────────────────────────────────────────┐ │
│  │  Step 4: 激活任务 (activate_task → enqueue_task)                              │ │
│  │  ┌──────────────────────────────────────────────────────────────────────────┐ │ │
│  │  │  // 根据调度类调用不同的enqueue函数                                      │ │ │
│  │  │  p->sched_class->enqueue_task(rq, p, flags);                            │ │ │
│  │  │                                                                          │ │ │
│  │  │  // CFS调度类 (kernel/sched/fair.c):                                    │ │ │
│  │  │  ┌────────────────────────────────────────────────────────────────────┐ │ │ │
│  │  │  │  place_entity(cfs_rq, se, flags);  // 设置vruntime                │ │ │ │
│  │  │  │  __enqueue_entity(cfs_rq, se);     // 插入红黑树                  │ │ │ │
│  │  │  │  account_entity_enqueue(cfs_rq, se); // 更新负载统计               │ │ │ │
│  │  │  └────────────────────────────────────────────────────────────────────┘ │ │ │
│  │  │                                                                          │ │ │
│  │  │  rq->nr_running++;                                                      │ │ │
│  │  └──────────────────────────────────────────────────────────────────────────┘ │ │
│  └────────────────────────────────────────────────────────────────────────────────┘ │
│                                      │                                               │
│                                      ▼                                               │
│  ┌────────────────────────────────────────────────────────────────────────────────┐ │
│  │  Step 5: 检查是否需要抢占当前进程                                             │ │
│  │  ┌──────────────────────────────────────────────────────────────────────────┐ │ │
│  │  │  check_preempt_curr(rq, p, flags);                                      │ │ │
│  │  │  ┌────────────────────────────────────────────────────────────────────┐ │ │ │
│  │  │  │  if (p->sched_class->prio > rq->curr->sched_class->prio) {        │ │ │ │
│  │  │  │      resched_curr(rq);  // 设置 TIF_NEED_RESCHED 标志             │ │ │ │
│  │  │  │  }                                                                  │ │ │ │
│  │  │  └────────────────────────────────────────────────────────────────────┘ │ │ │
│  │  └──────────────────────────────────────────────────────────────────────────┘ │ │
│  └────────────────────────────────────────────────────────────────────────────────┘ │
│                                      │                                               │
│                                      ▼                                               │
│  ┌────────────────────────────────────────────────────────────────────────────────┐ │
│  │  输出: 成功唤醒返回 1                                                          │ │
│  └────────────────────────────────────────────────────────────────────────────────┘ │
│                                                                                      │
└─────────────────────────────────────────────────────────────────────────────────────┘

4.2 负载均衡触发数据流

┌─────────────────────────────────────────────────────────────────────────────────────┐
│                        负载均衡触发数据流                                            │
├─────────────────────────────────────────────────────────────────────────────────────┤
│                                                                                      │
│  时钟中断路径(运行时):                                                             │
│  ┌────────────────────────────────────────────────────────────────────────────────┐ │
│  │  arch/arm64/kernel/time.c                                                     │ │
│  │  timer_interrupt()                                                            │ │
│  │       │                                                                        │ │
│  │       ▼                                                                        │ │
│  │  kernel/time/tick-common.c                                                    │ │
│  │  tick_handle_periodic()                                                        │ │
│  │       │                                                                        │ │
│  │       ▼                                                                        │ │
│  │  kernel/time/timer.c                                                          │ │
│  │  update_process_times()                                                        │ │
│  │       │                                                                        │ │
│  │       ▼                                                                        │ │
│  │  kernel/sched/core.c                                                          │ │
│  │  scheduler_tick()                                                              │ │
│  │       │                                                                        │ │
│  │       ├─► curr->sched_class->task_tick(rq, curr, 0)  // 更新任务时间片       │ │
│  │       │                                                                        │ │
│  │       └─► trigger_load_balance(rq)                                            │ │
│  │                │                                                               │ │
│  │                ▼                                                               │ │
│  │            raise_softirq(SCHED_SOFTIRQ)  // 触发调度软中断                    │ │
│  └────────────────────────────────────────────────────────────────────────────────┘ │
│                                      │                                               │
│                                      ▼                                               │
│  软中断路径:                                                                         │
│  ┌────────────────────────────────────────────────────────────────────────────────┐ │
│  │  kernel/sched/core.c                                                          │ │
│  │  run_rebalance_domains()  [软中断处理函数]                                    │ │
│  │       │                                                                        │ │
│  │       ▼                                                                        │ │
│  │  kernel/sched/fair.c                                                          │ │
│  │  rebalance_domains(this_cpu, idle)                                            │ │
│  │       │                                                                        │ │
│  │       ├─► for_each_domain(cpu, sd) {  // 遍历所有调度域                       │ │
│  │       │       load_balance(cpu, rq, sd, idle, &balance);                      │ │
│  │       │   }                                                                    │ │
│  │       │                                                                        │ │
│  │       ▼                                                                        │ │
│  │  load_balance()  // 核心负载均衡函数                                          │ │
│  └────────────────────────────────────────────────────────────────────────────────┘ │
│                                      │                                               │
│                                      ▼                                               │
│  负载均衡核心(kernel/sched/fair.c):                                                │
│  ┌────────────────────────────────────────────────────────────────────────────────┐ │
│  │  load_balance():                                                              │ │
│  │  ┌──────────────────────────────────────────────────────────────────────────┐ │ │
│  │  │  1. find_busiest_group()  // 找出最忙调度组                              │ │ │
│  │  │       │                                                                  │ │ │
│  │  │       ├─► update_sd_lb_stats()  // 更新组内负载统计                      │ │ │
│  │  │       └─► 找出平均负载最高的组                                           │ │ │
│  │  │                                                                          │ │ │
│  │  │  2. find_busiest_queue()   // 找出最忙CPU队列                            │ │ │
│  │  │       │                                                                  │ │ │
│  │  │       └─► 遍历组内CPU,找出负载最高的                                    │ │ │
│  │  │                                                                          │ │ │
│  │  │  3. move_tasks()            // 迁移任务                                  │ │ │
│  │  │       │                                                                  │ │ │
│  │  │       ├─► 遍历任务(从高优先级到低优先级)                               │ │ │
│  │  │       ├─► 检查亲和性限制 (cpus_allowed)                                 │ │ │
│  │  │       ├─► 检查迁移代价                                                  │ │ │
│  │  │       └─► 执行迁移: detach_task() + attach_task()                       │ │ │
│  │  │                                                                          │ │ │
│  │  │  4. 如果迁移失败且调度域允许主动均衡 → 触发主动均衡                      │ │ │
│  │  │       └─► 设置 active_balance 标志,唤醒 migration_thread               │ │ │
│  │  └──────────────────────────────────────────────────────────────────────────┘ │ │
│  └────────────────────────────────────────────────────────────────────────────────┘ │
│                                                                                      │
└─────────────────────────────────────────────────────────────────────────────────────┘

第五部分:调度器运用树形分析

5.1 调度器类优先级层次

┌─────────────────────────────────────────────────────────────────────────────────────┐
│                             调度器类优先级层次                                       │
├─────────────────────────────────────────────────────────────────────────────────────┤
│                                                                                      │
│  优先级从高到低(kernel/sched/sched.h中的调度类链表顺序):                          │
│  ┌────────────────────────────────────────────────────────────────────────────────┐ │
│  │                                                                                │ │
│  │  ┌──────────────────────────────────────────────────────────────────────────┐ │ │
│  │  │  stop_sched_class        (最高优先级)                                    │ │ │
│  │  │  ├─ 用于 stop_machine() 机制                                            │ │ │
│  │  │  ├─ 执行时停止所有其他任务                                              │ │ │
│  │  │  └─ 用于CPU热插拔、ftrace等                                              │ │ │
│  │  └──────────────────────────────────────────────────────────────────────────┘ │ │
│  │                                      │                                         │ │
│  │                                      ▼                                         │ │
│  │  ┌──────────────────────────────────────────────────────────────────────────┐ │ │
│  │  │  dl_sched_class           (Deadline调度)                                 │ │ │
│  │  │  ├─ SCHED_DEADLINE 策略                                                 │ │ │
│  │  │  ├─ 任务有明确的截止时间要求                                            │ │ │
│  │  │  └─ 使用 CBS (Constant Bandwidth Server) 算法                          │ │ │
│  │  └──────────────────────────────────────────────────────────────────────────┘ │ │
│  │                                      │                                         │ │
│  │                                      ▼                                         │ │
│  │  ┌──────────────────────────────────────────────────────────────────────────┐ │ │
│  │  │  rt_sched_class           (实时调度)                                     │ │ │
│  │  │  ├─ SCHED_FIFO: 先入先出,运行直到主动让出                              │ │ │
│  │  │  ├─ SCHED_RR: 时间片轮转                                                │ │ │
│  │  │  ├─ 优先级范围 0-99 (数字越大优先级越高)                                │ │ │
│  │  │  └─ 使用优先级位图快速查找                                              │ │ │
│  │  └──────────────────────────────────────────────────────────────────────────┘ │ │
│  │                                      │                                         │ │
│  │                                      ▼                                         │ │
│  │  ┌──────────────────────────────────────────────────────────────────────────┐ │ │
│  │  │  fair_sched_class         (CFS完全公平调度)                              │ │ │
│  │  │  ├─ SCHED_NORMAL: 普通进程                                              │ │ │
│  │  │  ├─ SCHED_BATCH: 批处理进程                                             │ │ │
│  │  │  ├─ SCHED_IDLE: 空闲优先级                                             │ │ │
│  │  │  ├─ 使用红黑树管理运行队列                                              │ │ │
│  │  │  └─ 基于 vruntime 选择下一个任务                                        │ │ │
│  │  └──────────────────────────────────────────────────────────────────────────┘ │ │
│  │                                      │                                         │ │
│  │                                      ▼                                         │ │
│  │  ┌──────────────────────────────────────────────────────────────────────────┐ │ │
│  │  │  idle_sched_class         (空闲调度)                                     │ │ │
│  │  │  ├─ 没有其他任务时运行                                                  │ │ │
│  │  │  ├─ 执行 idle 任务 (CPU idle loop)                                      │ │ │
│  │  │  └─ 触发 CPU 省电模式 (WFI/WFE on ARM64)                                │ │ │
│  │  └──────────────────────────────────────────────────────────────────────────┘ │ │
│  │                                                                                │ │
│  └────────────────────────────────────────────────────────────────────────────────┘ │
│                                                                                      │
│  调度类链表定义(kernel/sched/core.c):                                              │
│  ┌────────────────────────────────────────────────────────────────────────────────┐ │
│  │  static const struct sched_class * const sched_class_highest =               │ │
│  │      &stop_sched_class,                                                       │ │
│  │      &dl_sched_class,                                                         │ │
│  │      &rt_sched_class,                                                         │ │
│  │      &fair_sched_class,                                                       │ │
│  │      &idle_sched_class,                                                       │ │
│  │  };                                                                           │ │
│  └────────────────────────────────────────────────────────────────────────────────┘ │
│                                                                                      │
└─────────────────────────────────────────────────────────────────────────────────────┘

5.2 pick_next_task() 核心逻辑

┌─────────────────────────────────────────────────────────────────────────────────────┐
│                    pick_next_task() 程序流程图                                      │
├─────────────────────────────────────────────────────────────────────────────────────┤
│                                                                                      │
│  ┌────────────────────────────────────────────────────────────────────────────────┐ │
│  │  pick_next_task(struct rq *rq, struct task_struct *prev)                      │ │
│  └────────────────────────────────────────────────────────────────────────────────┘ │
│                                      │                                               │
│                                      ▼                                               │
│  ┌────────────────────────────────────────────────────────────────────────────────┐ │
│  │  // 优化1: 如果队列中只有CFS任务,直接调用公平调度类                          │ │
│  │  if (likely(rq->nr_running == rq->cfs.h_nr_running)) {                        │ │
│  │      p = fair_sched_class.pick_next_task(rq);                                 │ │
│  │      if (likely(p != RETRY_TASK)) return p;                                   │ │
│  │  }                                                                            │ │
│  └────────────────────────────────────────────────────────────────────────────────┘ │
│                                      │                                               │
│                                      ▼                                               │
│  ┌────────────────────────────────────────────────────────────────────────────────┐ │
│  │  // 通用路径:按优先级遍历所有调度类                                           │ │
│  │  for_each_class(class) {                                                      │ │
│  │      p = class->pick_next_task(rq);                                           │ │
│  │      if (p) return p;                                                         │ │
│  │  }                                                                            │ │
│  │  // 理论上一定会返回idle任务,所以不会返回NULL                                 │ │
│  └────────────────────────────────────────────────────────────────────────────────┘ │
│                                                                                      │
│  ┌────────────────────────────────────────────────────────────────────────────────┐ │
│  │  fair_sched_class.pick_next_task() 实现 (kernel/sched/fair.c)                 │ │
│  │  ┌──────────────────────────────────────────────────────────────────────────┐ │ │
│  │  │  pick_next_task_fair():                                                  │ │ │
│  │  │  ┌────────────────────────────────────────────────────────────────────┐ │ │ │
│  │  │  │  1. 从当前运行队列的cfs_rq中获取最左边的红黑树节点                 │ │ │ │
│  │  │  │     se = pick_next_entity(cfs_rq);                                 │ │ │ │
│  │  │  │                                                                    │ │ │ │
│  │  │  │  2. 如果存在组调度(group scheduling),处理嵌套cfs_rq              │ │ │ │
│  │  │  │     while (se && se->my_q) {                                      │ │ │ │
│  │  │  │         se = pick_next_entity(se->my_q);                          │ │ │ │
│  │  │  │     }                                                              │ │ │ │
│  │  │  │                                                                    │ │ │ │
│  │  │  │  3. 返回对应的task_struct                                        │ │ │ │
│  │  │  │     return task_of(se);                                           │ │ │ │
│  │  │  └────────────────────────────────────────────────────────────────────┘ │ │ │
│  │  └──────────────────────────────────────────────────────────────────────────┘ │ │
│  └────────────────────────────────────────────────────────────────────────────────┘ │
│                                                                                      │
└─────────────────────────────────────────────────────────────────────────────────────┘

第六部分:关键函数树形分析

6.1 核心调度函数调用树

┌─────────────────────────────────────────────────────────────────────────────────────┐
│                           关键函数调用树                                            │
├─────────────────────────────────────────────────────────────────────────────────────┤
│                                                                                      │
│  schedule() (kernel/sched/core.c)                                                  │
│  │                                                                                  │
│  └─► __schedule(false)                                                             │
│       │                                                                             │
│       ├─► preempt_disable()                       // 关闭抢占                      │
│       │                                                                             │
│       ├─► raw_spin_lock_irq(&rq->lock)           // 获取运行队列锁                 │
│       │                                                                             │
│       ├─► update_rq_clock(rq)                    // 更新队列时钟                   │
│       │                                                                             │
│       ├─► pick_next_task(rq, prev, &rf)          // 选择下一个任务                 │
│       │   │                                                                         │
│       │   ├─► fair_sched_class.pick_next_task()                                    │
│       │   │   └─► pick_next_task_fair()                                            │
│       │   │       └─► pick_next_entity()                                           │
│       │   │           └─► __pick_first_entity()  // 红黑树最左节点                 │
│       │   │                                                                         │
│       │   ├─► rt_sched_class.pick_next_task()                                      │
│       │   │   └─► pick_next_task_rt()                                              │
│       │   │       └─► 优先级位图查找                                              │
│       │   │                                                                         │
│       │   └─► idle_sched_class.pick_next_task()                                    │
│       │       └─► pick_next_task_idle()  // 返回 idle 任务                         │
│       │                                                                             │
│       ├─► context_switch(rq, prev, next, &rf)    // 上下文切换                     │
│       │   │                                                                         │
│       │   ├─► switch_mm_irqs_off(&prev->mm, &next->mm, next)  // 切换内存空间      │
│       │   │                                                                         │
│       │   ├─► switch_to(prev, next, prev)        // 切换CPU寄存器                  │
│       │   │   └─► arch/arm64/kernel/entry.S: __switch_to()                         │
│       │   │                                                                         │
│       │   └─► finish_task_switch(prev)          // 清理前一个任务                  │
│       │                                                                             │
│       └─► raw_spin_unlock_irq(&rq->lock)        // 释放锁                          │
│            │                                                                        │
│            └─► preempt_enable()                  // 重新启用抢占                   │
│                                                                                      │
├─────────────────────────────────────────────────────────────────────────────────────┤
│                                                                                      │
│  try_to_wake_up() (kernel/sched/core.c)                                            │
│  │                                                                                  │
│  └─► ttwu_queue(p, cpu)                                                           │
│       │                                                                             │
│       ├─► ttwu_queue_remote(p, cpu)           // 跨CPU唤醒                         │
│       │   └─► smp_send_reschedule(cpu)        // 发送IPI                          │
│       │                                                                             │
│       └─► ttwu_do_activate()                  // 同CPU唤醒                         │
│           │                                                                         │
│           ├─► activate_task()                                                      │
│           │   └─► enqueue_task()                                                   │
│           │       └─► p->sched_class->enqueue_task()                               │
│           │                                                                         │
│           └─► ttwu_do_wakeup()                                                     │
│               └─► check_preempt_curr()                                             │
│                   └─► resched_curr()          // 设置 TIF_NEED_RESCHED             │
│                                                                                      │
├─────────────────────────────────────────────────────────────────────────────────────┤
│                                                                                      │
│  load_balance() (kernel/sched/fair.c) [SMP专用]                                    │
│  │                                                                                  │
│  ├─► find_busiest_group()                                                          │
│  │   └─► update_sd_lb_stats()                     // 更新调度域统计               │
│  │                                                                                  │
│  ├─► find_busiest_queue()                                                          │
│  │   └─► 遍历组内CPU,计算负载                                                    │
│  │                                                                                  │
│  ├─► move_tasks()                                                                  │
│  │   ├─► detach_tasks()                       // 从源队列移除任务                 │
│  │   └─► attach_tasks()                       // 添加到目标队列                   │
│  │                                                                                  │
│  └─► active_load_balance()                   // 迁移失败时的主动均衡              │
│      └─► stop_one_cpu_nowait()               // 使用stop类迁移任务                │
│                                                                                      │
└─────────────────────────────────────────────────────────────────────────────────────┘

6.2 SMP启动流程(ARM64)

┌─────────────────────────────────────────────────────────────────────────────────────┐
│                    ARM64 SMP 启动流程图                                             │
├─────────────────────────────────────────────────────────────────────────────────────┤
│                                                                                      │
│  ┌────────────────────────────────────────────────────────────────────────────────┐ │
│  │  Boot ROM → ATF (ARM Trusted Firmware) → Bootloader → Kernel entry            │ │
│  └────────────────────────────────────────────────────────────────────────────────┘ │
│                                      │                                               │
│                                      ▼                                               │
│  ┌────────────────────────────────────────────────────────────────────────────────┐ │
│  │  CPU0 (主核) 启动流程:                                                         │ │
│  │  ┌──────────────────────────────────────────────────────────────────────────┐ │ │
│  │  │  arch/arm64/kernel/head.S                                               │ │ │
│  │  │  _text (入口点)                                                          │ │ │
│  │  │       │                                                                  │ │ │
│  │  │       ├─► 设置页表、使能MMU                                             │ │ │
│  │  │       └─► 跳转到 start_kernel                                            │ │ │
│  │  │                                                                          │ │ │
│  │  │  init/main.c                                                             │ │ │
│  │  │  start_kernel()                                                          │ │ │
│  │  │       │                                                                  │ │ │
│  │  │       ├─► setup_arch()            // arch/arm64/kernel/setup.c          │ │ │
│  │  │       │       │                                                          │ │ │
│  │  │       │       └─► smp_init_cpus()  // 探测CPU数量                        │ │ │
│  │  │       │            └─► of_parse_and_init_cpus() // 从设备树读取          │ │ │
│  │  │       │                                                                  │ │ │
│  │  │       ├─► smp_prepare_cpus()       // 准备启动secondary CPU              │ │ │
│  │  │       │       │                                                          │ │ │
│  │  │       │       └─► 根据启动方式选择:                                       │ │ │
│  │  │       │           ├─► smp_spin_table_ops (自旋表)                        │ │ │
│  │  │       │           └─► smp_psci_ops (PSCI固件)                           │ │ │
│  │  │       │                                                                  │ │ │
│  │  │       ├─► rest_init()                                                    │ │ │
│  │  │       │       │                                                          │ │ │
│  │  │       │       ├─► kernel_thread(kernel_init, ...)  // 创建init进程       │ │ │
│  │  │       │       └─► cpu_startup_entry(CPUHP_ONLINE)   // 进入idle循环      │ │ │
│  │  │       │                                                                  │ │ │
│  │  │       └─► smp_init()               // 正式启动secondary CPU              │ │ │
│  │  │               │                                                          │ │ │
│  │  │               └─► for_each_present_cpu(cpu) {                           │ │ │
│  │  │                       cpu_up(cpu);                                       │ │ │
│  │  │                   }                                                      │ │ │
│  │  └──────────────────────────────────────────────────────────────────────────┘ │ │
│  └────────────────────────────────────────────────────────────────────────────────┘ │
│                                      │                                               │
│                                      ▼                                               │
│  ┌────────────────────────────────────────────────────────────────────────────────┐ │
│  │  CPU1...n (从核) 启动流程:                                                    │ │
│  │  ┌──────────────────────────────────────────────────────────────────────────┐ │ │
│  │  │                                                                          │ │ │
│  │  │  1. CPU0 通过 PSCI 或 自旋表 发送启动信号                               │ │ │
│  │  │       │                                                                  │ │ │
│  │  │       ▼                                                                  │ │ │
│  │  │  2. arch/arm64/kernel/head.S: secondary_startup()                       │ │ │
│  │  │       │                                                                  │ │ │
│  │  │       ├─► 等待 pen_release == cpu_id (自旋表方式)                        │ │ │
│  │  │       └─► 跳转到 secondary_startup_kernel()                             │ │ │
│  │  │                                                                          │ │ │
│  │  │  3. arch/arm64/kernel/smp.c: smp_secondary_init(cpu)                    │ │ │
│  │  │       │                                                                  │ │ │
│  │  │       └─► 设置 pen_release = -1 (通知CPU0完成)                          │ │ │
│  │  │                                                                          │ │ │
│  │  │  4. start_secondary()                                                   │ │ │
│  │  │       │                                                                  │ │ │
│  │  │       ├─► cpu_init()               // 初始化CPU寄存器                    │ │ │
│  │  │       ├─► 初始化 per-CPU 数据                                           │ │ │
│  │  │       ├─► 设置 current 指向 idle 任务                                   │ │ │
│  │  │       ├─► notify_cpu_starting(cpu) // 通知其他子系统                    │ │ │
│  │  │       ├─► set_cpu_online(cpu, true) // 标记CPU在线                      │ │ │
│  │  │       └─► cpu_startup_entry(CPUHP_ONLINE)  // 进入 idle 循环            │ │ │
│  │  └──────────────────────────────────────────────────────────────────────────┘ │ │
│  └────────────────────────────────────────────────────────────────────────────────┘ │
│                                                                                      │
└─────────────────────────────────────────────────────────────────────────────────────┘

第七部分:调试流程树形分析

7.1 运行时调试接口

┌─────────────────────────────────────────────────────────────────────────────────────┐
│                        运行时调试接口(目标系统)                                    │
├─────────────────────────────────────────────────────────────────────────────────────┤
│                                                                                      │
│  /proc 接口:                                                                        │
│  ┌────────────────────────────────────────────────────────────────────────────────┐ │
│  │  /proc/cpuinfo                     # CPU信息,包括processor、CPU part等       │ │
│  │  /proc/stat                        # CPU时间统计(user, system, idle等)      │ │
│  │  /proc/interrupts                  # 中断分布(每个CPU的IRQ计数)             │ │
│  │  /proc/softirqs                    # 软中断分布                               │ │
│  │  /proc/schedstat                   # 调度器统计信息                           │ │
│  │  /proc/[pid]/stat                  # 单个进程状态(包含运行的CPU)            │ │
│  │  /proc/[pid]/task/                 # 进程的线程信息                           │ │
│  └────────────────────────────────────────────────────────────────────────────────┘ │
│                                                                                      │
│  /sys 接口:                                                                         │
│  ┌────────────────────────────────────────────────────────────────────────────────┐ │
│  │  /sys/devices/system/cpu/          # CPU设备目录                              │ │
│  │  ├── cpu0/...                      # CPU0相关信息                             │ │
│  │  ├── cpu1/...                                                                  │ │
│  │  ├── present                       # 当前在线的CPU掩码                        │ │
│  │  ├── possible                      # 可能存在的CPU掩码                        │ │
│  │  ├── offline                       # 离线的CPU(可写,用于热插拔)            │ │
│  │  └── kernel_max                    # 最大CPU编号                              │ │
│  └────────────────────────────────────────────────────────────────────────────────┘ │
│                                                                                      │
│  命令行工具:                                                                        │
│  ┌────────────────────────────────────────────────────────────────────────────────┐ │
│  │  taskset -p [mask] [pid]       # 设置进程CPU亲和性                           │ │
│  │  chrt -f [prio] [pid]          # 设置实时优先级                              │ │
│  │  mpstat -P ALL 1               # 查看各CPU使用率                             │ │
│  │  top (按1查看各CPU)            # 实时监控                                    │ │
│  │  perf stat -e sched:* ./app    # 调度事件跟踪                                │ │
│  │  trace-cmd record -e sched*    # 调度器追踪                                  │ │
│  │  echo 0 > /sys/devices/system/cpu/cpu1/online # CPU热插拔(下线)            │ │
│  └────────────────────────────────────────────────────────────────────────────────┘ │
│                                                                                      │
└─────────────────────────────────────────────────────────────────────────────────────┘

7.2 常见SMP问题调试决策树

┌─────────────────────────────────────────────────────────────────────────────────────┐
│                    常见SMP问题调试决策树(ARM64)                                   │
├─────────────────────────────────────────────────────────────────────────────────────┤
│                                                                                      │
│  ┌────────────────────────────────────────────────────────────────────────────────┐ │
│  │  问题: 某个CPU占用率100%,系统响应慢                                          │ │
│  └────────────────────────────────────────────────────────────────────────────────┘ │
│                                      │                                               │
│                                      ▼                                               │
│  ┌────────────────────────────────────────────────────────────────────────────────┐ │
│  │  Step 1: 确认问题CPU                                                          │ │
│  │  $ top -1                                                                    │ │
│  │  $ mpstat -P ALL 1                                                            │ │
│  └────────────────────────────────────────────────────────────────────────────────┘ │
│                                      │                                               │
│                    ┌─────────────────┼─────────────────┐                           │
│                    │                 │                 │                           │
│                    ▼                 ▼                 ▼                           │
│            ┌──────────────┐  ┌──────────────┐  ┌──────────────┐                   │
│            │ 用户态进程   │  │ 内核线程     │  │ 软中断       │                   │
│            │ 占用高       │  │ 占用高       │  │ 占用高       │                   │
│            └──────┬───────┘  └──────┬───────┘  └──────┬───────┘                   │
│                   │                 │                 │                           │
│                   ▼                 ▼                 ▼                           │
│            ┌──────────────┐  ┌──────────────┐  ┌──────────────┐                   │
│            │ $ perf top   │  │ $ ps -eLf    │  │ $ cat/proc/  │                   │
│            │ -C [cpu]     │  │ 查看ksoftirqd│  │ softirqs     │                   │
│            └──────────────┘  └──────────────┘  └──────────────┘                   │
│                                                                                      │
├─────────────────────────────────────────────────────────────────────────────────────┤
│                                                                                      │
│  ┌────────────────────────────────────────────────────────────────────────────────┐ │
│  │  问题: 锁竞争严重,性能下降                                                    │ │
│  └────────────────────────────────────────────────────────────────────────────────┘ │
│                                      │                                               │
│                                      ▼                                               │
│  ┌────────────────────────────────────────────────────────────────────────────────┐ │
│  │  Step 1: 分析锁等待                                                           │ │
│  │  $ perf lock record -a sleep 10                                               │ │
│  │  $ perf lock report                                                            │ │
│  │                                                                                │ │
│  │  Step 2: 查看自旋锁统计(需要内核配置CONFIG_LOCK_STAT)                       │ │
│  │  $ cat /proc/lock_stat                                                         │ │
│  │                                                                                │ │
│  │  Step 3: 使用lockdep检测死锁(需要内核配置CONFIG_LOCKDEP)                    │ │
│  │  # 查看 /proc/lockdep_chain                                                    │ │
│  │  # 查看 /proc/lockdep_stats                                                    │ │
│  └────────────────────────────────────────────────────────────────────────────────┘ │
│                                                                                      │
├─────────────────────────────────────────────────────────────────────────────────────┤
│                                                                                      │
│  ┌────────────────────────────────────────────────────────────────────────────────┐ │
│  │  问题: 负载不均衡,某些CPU空闲而其他忙碌(big.LITTLE架构常见)                 │ │
│  └────────────────────────────────────────────────────────────────────────────────┘ │
│                                      │                                               │
│                                      ▼                                               │
│  ┌────────────────────────────────────────────────────────────────────────────────┐ │
│  │  Step 1: 查看调度域配置                                                       │ │
│  │  $ cat /proc/sys/kernel/sched_domain/cpu*/domain*/flags                       │ │
│  │                                                                                │ │
│  │  Step 2: 查看EAS(能量感知调度)状态                                          │ │
│  │  $ cat /proc/sys/kernel/sched_energy_aware                                    │ │
│  │                                                                                │ │
│  │  Step 3: 调整负载均衡参数                                                     │ │
│  │  # 减少负载均衡间隔                                                           │ │
│  │  echo 1 > /proc/sys/kernel/sched_min_interval                                 │ │
│  │                                                                                │ │
│  │  # 允许更激进的任务迁移                                                       │ │
│  │  echo 1 > /proc/sys/kernel/sched_migration_cost_ns                            │ │
│  │                                                                                │ │
│  │  Step 4: 使用trace-cmd追踪负载均衡                                            │ │
│  │  $ trace-cmd record -e sched:sched_migrate_task -e sched:sched_balance*       │ │
│  └────────────────────────────────────────────────────────────────────────────────┘ │
│                                                                                      │
└─────────────────────────────────────────────────────────────────────────────────────┘

第八部分:总结对比表

分析维度 编译前(源码树) 运行时(目标系统)
源码位置 开发者下载的 linux-6.1/ 目录 /lib/modules/$(uname -r)/build/(符号链接)
头文件 include/linux/*.h, arch/arm64/include/asm/*.h /usr/include/linux/(用户态头文件,不同)
核心数据结构定义 include/linux/sched.h, kernel/sched/sched.h 只能通过 /proc/sys 查看运行时状态
函数实现 kernel/sched/core.c, kernel/sched/fair.c 只能通过 System.map 查看地址,无法查看源码
调试接口 CONFIG_DEBUG_* 编译选项,printk() /proc/*, /sys/*, perf, trace-cmd
修改方式 编辑源码 → 重新编译 → 安装新内核 只能修改 /proc/sys/kernel/sched_* 运行时参数

核心要点

  1. 编译前:开发者分析 arch/arm64/kernel/smp.ckernel/sched/ 等源码文件

  2. 运行时:系统管理员使用 mpstat -P ALLtaskset/proc/interrupts 等工具

  3. 不要混淆/usr/src/linux 通常不存在,需要手动安装 linux-source

Logo

汇聚全球AI编程工具,助力开发者即刻编程。

更多推荐