架构)
Android 内核调度器在通用 Linux 调度器(CFS、RT、DL)的基础上,面临着三个独特的工程挑战:UI 线程的响应性保障、功耗与性能的动态平衡,以及多核异构(big.LITTLE)架构下的负载分配。这些挑战直接决定了用户对系统流畅度和续航的主观体验。3.1 UI 线程调度:从“公平”到“响应优先”通用 Linux CFS 调度器的核心目标是“公平”,即让每个就绪线程获得等比例的 CPU 时间。然而,Android 的 UI 渲染管线(Choreographer + SurfaceFlinger)对调度延迟极其敏感:一个 16.6ms 的垂直同步周期内,如果 UI 线程或 RenderThread 未能及时获得 CPU,就会导致掉帧(Jank)。核心矛盾:CFS 的“公平时间片”分配模式,无法保证 UI 线程在ms 级时间窗口内的即时唤醒与执行。UI 线程需要的是“低延迟”而非“高吞吐”。3.1.1 UI 线程的调度特征与识别线程类型调度特征关键指标调度器关注点UI Thread (主线程)短突发、高优先级、与 Input/VSYNC 强绑定调度延迟 3ms优先唤醒、避免被后台任务抢占RenderThread与 GPU 同步、计算渲染命令帧时间 16.6ms绑定到大核、避免 CPU 频率切换SurfaceFlinger合成图层、触发 HWC合成延迟 2msRT 优先级、独占 CPU 核心Binder ThreadsIPC 通信、阻塞等待Binder 响应时间避免优先级反转3.1.2 关键调度机制:cgroup 与优先级映射Android 通过cgroup(控制组)对 UI 相关线程进行分组管理,并配合schedtune(或新版内核的uclamp)机制,向调度器传递“性能偏好”提示。# 查看 UI 相关线程的 cgroup 分组 adb shell cat /dev/cpuset/top-app/tasks # 输出示例:包含当前前台应用的 UI 线程、RenderThread 等 # 查看 schedtune 的 boost 值(旧版内核) adb shell cat /dev/stune/top-app/schedtune.boost # 输出:10 (表示轻度 boost,倾向于大核) # 查看 uclamp 值(新版内核,4.19+) adb shell cat /sys/fs/cgroup/cpu/top-app/cpu.uclamp.latency_sensitive # 输出:1 (标记为延迟敏感)调优实践:在自定义内核中,可以通过修改schedtune.boost的默认值(0~100)来调整 UI 线程的“大核倾向性”。但过高的 boost 会导致小核空闲、功耗激增。推荐值为 10~30。3.2 功耗与性能平衡:EAS 调度器的核心博弈Android 从内核 4.14 开始全面引入EAS(Energy-Aware Scheduling,能耗感知调度),其核心思想是:在保证性能的前提下,选择能耗最低的 CPU 核心执行任务。EAS 的决策依赖于两个关键模型:CPU 的能耗模型(Energy Model, EM)和任务的性能需求模型(Task Utilization)。3.2.1 EAS 的调度决策流程任务利用率追踪:PELT(Per-Entity Load Tracking)算法追踪每个任务的 CPU 利用率(util_avg),范围 0~1024。CPU 容量评估:每个 CPU 核心的“最大容量”(capacity)由频率和微架构决定。大核容量通常为 1024,小核为 400~600。能耗计算:对于每个可能的 CPU,EAS 计算“预估能耗 = 任务利用率 × 该 CPU 的每单位利用率能耗”。选择最优 CPU: