3、Governor详解(上):Performance Governor原理、Powersave Governor原理、Userspace Governor原理
好,咱们今天正式进入Governor的世界。说实话,很多做嵌入式或者服务器调优的朋友,对Governor的理解就停留在「省电模式」和「性能模式」这两个词上。但实际工作中,选错了Governor,轻则功耗失控,重则系统卡顿甚至宕机。我见过不止一次,有人把服务器设成Powersave,结果数据库查询延迟直接飙到秒级。
今天我们先讲三个最基础的Governor:Performance、Powersave和Userspace。它们虽然简单,但理解透了,后面讲Ondemand和Interactive时你才能举一反三。
3.1 Performance Governor:简单粗暴,但有用
Performance Governor的逻辑,说白了就一句话:CPU永远跑在最高频率。不管系统有没有负载,它都死守最高频点。
核心行为:
- 设置CPU频率为最高可用频率(scaling_max_freq)
- 不响应负载变化,不做任何调频决策
- 功耗最高,延迟最低
你可能会问:「这玩意儿有啥用?不是浪费电吗?」嗯,我刚开始也这么想。直到有一次我在做实时音视频编解码的项目,发现CPU在低负载时被降频,导致编码器偶尔丢帧。换成Performance后,问题立刻消失。说白了,有些场景下,延迟比功耗更重要。
看看它的内核代码实现,其实非常简单:
// drivers/cpufreq/cpufreq_performance.c
static int cpufreq_governor_performance(struct cpufreq_policy *policy,
unsigned int event)
{
switch (event) {
case CPUFREQ_GOV_START:
case CPUFREQ_GOV_LIMITS:
// 直接设置到最高频率
__cpufreq_driver_target(policy, policy->max, CPUFREQ_RELATION_H);
break;
default:
break;
}
return 0;
}
看到了吗?就两个case,一个启动,一个限制变化。没有定时器,没有负载采样,没有任何花哨的逻辑。我曾经在调试一个功耗敏感的设备时,发现Performance模式下CPU温度直接飙到85度,但响应时间稳定在1ms以内。这就是它的代价——用功耗换确定性。
我的建议:
Performance Governor适合以下场景:
- 实时性要求高的任务(音频、视频、工业控制)
- 短时间爆发性计算(比如编译、渲染)
- 服务器端对延迟敏感的服务(比如高频交易)
但注意,别在笔记本或手机上长期开它,电池会哭的。
3.2 Powersave Governor:省电的极端
和Performance相反,Powersave Governor让CPU永远跑在最低频率。它的逻辑同样简单:
核心行为:
- 设置CPU频率为最低可用频率(scaling_min_freq)
- 同样不响应负载变化
- 功耗最低,延迟最高
你想想看,如果系统一直跑在最低频,那省电效果肯定好。但代价是什么?我举个例子:有一次我在调试一个IoT网关设备,默认用了Powersave Governor。结果设备在收到网络数据包时,CPU需要花几十毫秒才能从低频率「爬」上来处理中断。嗯,网络丢包率直接爆表。
它的代码实现和Performance几乎对称:
// drivers/cpufreq/cpufreq_powersave.c
static int cpufreq_governor_powersave(struct cpufreq_policy *policy,
unsigned int event)
{
switch (event) {
case CPUFREQ_GOV_START:
case CPUFREQ_GOV_LIMITS:
// 直接设置到最低频率
__cpufreq_driver_target(policy, policy->min, CPUFREQ_RELATION_L);
break;
default:
break;
}
return 0;
}
注意看,它用的是CPUFREQ_RELATION_L,表示选择小于等于目标频率的最低可用频率。而Performance用的是CPUFREQ_RELATION_H,选择大于等于目标频率的最高可用频率。这两个宏的区别,我建议你记住,后面调优时会用到。
避坑指南:
我曾经在一个嵌入式项目里,把Powersave设为默认Governor,结果系统在启动阶段加载驱动时,因为频率太低导致I/O超时。后来我加了一个启动阶段的频率提升策略才解决。所以,不要在需要快速响应的场景下用Powersave,尤其是中断密集型的任务。
3.3 Userspace Governor:把控制权交给你
Userspace Governor就更有意思了。它不自己做调频决策,而是把频率设置接口暴露给用户空间。说白了,你想让CPU跑多快,你自己说了算。
它的工作原理是这样的:
- 内核提供一个sysfs接口:
/sys/devices/system/cpu/cpuX/cpufreq/scaling_setspeed - 用户空间程序(比如脚本、守护进程)通过写这个文件来设置频率
- 内核不做任何干预,完全听你的
我个人的习惯是,在调试阶段或者做定制化功耗管理时,会临时切换到Userspace Governor。比如我想测试某个频率下的性能表现,直接写一个值进去就行:
# 切换到Userspace Governor
echo userspace > /sys/devices/system/cpu/cpu0/cpufreq/scaling_governor
# 设置频率为1.2GHz
echo 1200000 > /sys/devices/system/cpu/cpu0/cpufreq/scaling_setspeed
它的内核实现也很直白:
// drivers/cpufreq/cpufreq_userspace.c
static int cpufreq_set(struct cpufreq_policy *policy, unsigned int freq)
{
int ret;
if (!policy->governor_enabled)
return -EINVAL;
// 直接调用驱动层的target接口
ret = __cpufreq_driver_target(policy, freq, CPUFREQ_RELATION_L);
if (!ret)
policy->cur = freq;
return ret;
}
注意这里有个细节:policy->governor_enabled这个标志位。如果Governor还没启动,你写setspeed会返回错误。我曾经踩过这个坑,在系统初始化阶段过早写频率,结果一直报错,排查了半天才发现是Governor还没加载完。
实用技巧:
Userspace Governor最适合做两件事:
- 性能测试:固定频率跑benchmark,排除调频干扰
- 定制化调频策略:比如根据温度、电池电量、用户行为等自定义调频逻辑
但注意,如果你没有写用户空间程序,千万别长期用Userspace。否则CPU会一直卡在你上次设置的频率上,不会自动调整。
3.4 三个Governor的对比总结
好了,三个Governor讲完了。我整理了一个表格,方便你对比:
| 特性 | Performance | Powersave | Userspace |
|---|---|---|---|
| 频率策略 | 固定最高频 | 固定最低频 | 用户自定义 |
| 负载响应 | 不响应 | 不响应 | 不响应(需用户程序控制) |
| 功耗表现 | 最高 | 最低 | 取决于用户设置 |
| 延迟表现 | 最低 | 最高 | 取决于用户设置 |
| 适用场景 | 实时、低延迟 | 后台、空闲任务 | 调试、定制化 |
| 内核代码量 | 约30行 | 约30行 | 约100行 |
看到没?Performance和Powersave就是两个极端,代码量都很少。Userspace稍微复杂一点,因为它要处理用户空间的请求。但整体来说,这三个Governor都属于「静态调频」的范畴——它们不会根据负载动态调整频率。
下一节我们会讲Ondemand和Conservative这两个动态调频Governor,那才是真正考验调优功底的地方。嗯,今天就先到这里,你先把这三个基础Governor吃透,后面才能跟上节奏。
一句话总结:
Performance保延迟,Powersave保功耗,Userspace保自由。选哪个,看你的业务优先级。