2. Android系统架构与CPU基础
要做好CPU调度与功耗优化,第一步不是急着改参数,而是建立一张清晰的“系统地图”:应用代码从哪一层开始,经过哪些软件栈,最终落到哪颗CPU核心、以什么频率和电压运行。只有把Android软件栈、Linux内核、CPU微架构、核心与簇、频率与电压、性能与功耗这几层关系串起来,后续的调度策略、绑核、限频、温控才有落脚点。
一、Android软件栈:从应用到硅片的纵向分层
Android是一个典型的分层系统。最上层是应用层,包括系统应用与第三方App;其下是Java API框架层(Framework),提供ActivityManager、WindowManager等服务;再往下是原生库与Android运行时(ART),负责图形、媒体、数据库以及字节码执行;最底层是Linux内核,包含进程调度、内存管理、电源管理、驱动等。CPU调度与功耗优化主要发生在内核层,但触发者往往来自上层。
理解这条纵向链路的意义在于:上层的一次滑动、一次视频解码、一次后台同步,最终都会转化为内核中的任务(task)和线程(thread),由调度器决定它们在哪个CPU上运行、运行多久。功耗问题也往往不是单层造成的,而是“上层频繁唤醒 + 内核调度不当 + 硬件高频运行”共同作用的结果。
二、Linux内核:调度的真正执行者
Linux内核是Android与硬件之间的桥梁。与CPU调度和功耗直接相关的子系统包括:进程调度器(CFS、实时调度、EAS等)、CPU频率调节框架(cpufreq)、CPU空闲管理(cpuidle)、热管理(thermal)、以及电源管理(PM)。内核通过sysfs和procfs向用户空间暴露大量可观测、可配置的节点。
# 查看当前CPU频率与调度信息
cat /sys/devices/system/cpu/cpu0/cpufreq/scaling_cur_freq
cat /sys/devices/system/cpu/cpu0/cpufreq/scaling_governor
cat /proc/cpuinfo
# 查看各核心负载与运行状态
top -H -p <pid>
cat /proc/<pid>/task/<tid>/stat
这些节点是后续调优的“仪表盘”。例如scaling_governor决定频率如何随负载变化,cpuinfo反映核心拓扑,task/stat中的utime、stime则帮助判断线程是计算密集还是等待唤醒。
三、CPU微架构、核心与簇
现代移动SoC普遍采用异构多核架构,即big.LITTLE或DynamIQ。核心被划分为若干簇(cluster),同一簇内核心通常共享频率域和电压域,簇间可以独立调频。典型结构是“超大核 + 大核 + 小核”三簇,分别面向瞬时爆发、持续性能和低功耗后台任务。
微架构决定了单核的每时钟周期指令数(IPC)、流水线深度、缓存层次和分支预测能力。同一频率下,不同微架构的算力与功耗差异很大。因此“频率高”不等于“性能好”,“核心多”也不等于“更省电”。调度器需要根据任务特性,把重负载放到大核、把轻负载或后台任务压到小核,才能兼顾响应与续航。
四、频率与电压:功耗的非线性来源
CPU的动态功耗近似满足 P ∝ C·V²·f,其中C为等效电容,V为工作电压,f为频率。频率提升往往需要同步提高电压才能稳定,因此功耗随频率呈超线性增长。这也是为什么“把频率拉满”在移动端通常得不偿失:性能可能只提升20%,功耗却可能翻倍。
内核通过OPP(Operating Performance Point)表管理频率与电压的对应关系。调频策略(governor)决定何时升频、何时降频。常见governor包括performance、powersave、schedutil、ondemand等。现代Android更倾向使用schedutil,因为它能结合调度器的负载信息做更及时的频率决策。
| 层级/对象 | 关注点 | 典型观测或配置 |
|---|---|---|
| 应用/Framework | 任务频率、唤醒次数、线程优先级 | Trace、Binder调用、Handler消息 |
| Linux内核 | 调度策略、频率选择、空闲状态 | schedutil、cpuidle、thermal |
| CPU核心/簇 | 任务放置、负载均衡、簇间迁移 | EAS、core_ctl、cpuinfo |
| 频率/电压 | OPP、电压轨、功耗曲线 | scaling_cur_freq、regulator |
| 性能/功耗 | 能效比、温控降频、续航 | PowerProfiler、能耗模型 |
五、案例与场景:一次滑动背后的调度链路
假设用户滑动列表,UI线程需要在一帧16.6ms内完成测量、布局和绘制。若此时小核正在处理后台同步,调度器可能把UI线程放到大核,并迅速提升该簇频率;绘制完成后负载下降,频率回落。若后台任务持续占用大核,就会挤压UI线程,造成掉帧和额外功耗。
六、常见误区与复盘
- 误区一:频率越高越流畅。 高频带来功耗和发热,发热后触发温控降频,反而可能更卡。
- 误区二:核心越多越好。 多核唤醒会增加漏电和调度开销,轻负载下应尽量合并到少量核心。
- 误区三:只看平均功耗。 瞬时功耗尖峰同样影响续航和温控,需要结合Trace看时间分布。
- 误区四:忽略电压域。 同簇共享电压,一个核心升频可能抬高整簇功耗。
本节的核心结论是:Android软件栈决定任务从哪来,Linux内核决定任务去哪跑,CPU微架构与核心簇决定跑得有多快,频率与电压决定代价有多大,而性能与功耗的平衡,正是CPU调度与功耗优化工程要持续求解的问题。