作为本系列文章的开篇之作,首先要向大家介绍的是 cpufreq,它是 Linux 2.6内核为了更好的支持近年来在各款主流CPU 处理器中出现的变频技术而新增的一个内核子系统。
Cpufreq 的由来
随着 energy efficient computing 和 performance per watt 等概念的推广以及高级配置与电源接口ACPI(Advanced Configuration and Power Interface)标准的发展,目前市场上的主流 CPU 都提供了对变频(frequency scaling)技术的支持。例如Intel?处理器所支持的 Enhanced SpeedStep? 技术和 AMD? 处理器所支持的 PowerNow! ? 技术,另外像最新的PowerPC?、ARM?、SPARC? 和 SuperH? 等处理器中也提供了类似的支持。参考资料中列出了当前 Linux 2.6内核所支持的具备变频技术的处理器。需要注意的是,这里要讨论的变频技术与大家以前所熟知的超频是两个不同的概念。超频是指通过提高核心电压等手段让处理器工作在非标准频率下的行为,这往往会造成 CPU 使用寿命缩短以及系统稳定性下降等严重后果。
虽然多个处理器生产厂家都提供了对变频技术的支持,但是其硬件实现和使用方法必然存在着细微甚至巨大的差别。这就使得每个处理器生产厂家都需要按照其特殊的硬件实现和使用方法向内核中添加代码,从而让自己产品中的变频技术在 Linux 中得到支持和使用。然而,这种内核开发模式所导致的后果是各个厂家的实现代码散落在 Linux 内核代码树的各个角落里,各种不同的实现之间没有任何代码是共享的,这给内核的维护以及将来添加对新的产品的支持都带来了巨大的开销,并直接导致了 cpufreq 内核子系统的诞生。实际上,正如前文所说,发明变频技术的目的是为了能够让系统在运行过程中随时根据系统负载的变化动态调整 CPU 的运行频率。这件事情可以分为两个部分,一部分是“做什么”的问题,另一部分是“怎么做”的问题。“做什么”是指如何根据系统负载的动态变化挑选出 CPU 合适的运行频率,而“怎么做”就是要按照选定的运行频率在选定的时间对 CPU 进行设置,使之真正工作在这一频率上。这也就是我们在软件设计中经常会遇到的机制 mechanism 与策略 policy 的问题,而设计良好的软件会在架构上保证二者是被清晰的隔离开的并通过规范定义的接口进行通信。
Cpufreq 的设计和使用
为了解决前文所提到的问题,一个新的内核子系统—— cpufreq 应运而生了。Cpufreq 为在Linux 内核中更好的支持不同 CPU 的变频技术提供了一个统一的设计框架,其软件结构如图 1 所示。
在 cpufreq 模块的底层,各个CPU 生产厂商只需根据其变频技术的硬件实现和使用方法提供与其 CPU 相关的变频驱动程序(CPU-specific drivers),例如 Intel 需要提供支持Enhanced SpeedStep 技术的 CPU 驱动程序,而 AMD 则需要提供支持 PowerNow! 技术的 CPU 驱动程序。
在 cpufreq 模块的上层,governor 作为选择合适的目标运行频率的决策者,根据一定的标准在适当的时刻选择出 CPU 适合的运行频率,并通过 cpufreq 模块定义的接口操作底层与 CPU 相关的变频驱动程序,将 CPU 设置运行在选定的运行频率上。
目前最新的 Linux 内核中提供了 performance 、powersave 、userspace、conservative 和 ondemand 五种 governors 供用户选择使用,它们在选择 CPU 合适的运行频率时使用的是各自不同的标准并分别适用于不同的应用场景。用户在同一时间只能选择其中一个 governor 使用,但是可以在系统运行过程中根据应用需求的变化而切换使用另一个 governor 。
这种设计带来的好处是使得 governor 和 CPU 相关的变频驱动程序的开发可以相互独立进行,并在最大限度上实现代码重用,内核开发人员在编写和试验新的 governor 时不会再陷入到某款特定 CPU 的变频技术的硬件实现细节中去,而 CPU 生产厂商在向 Linux 内核中添加支持其特定的 CPU 变频技术的代码时只需提供一个相对来说简单了很多的驱动程序,而不必考虑在各种不同的应用场景中如何选择合适的运行频率这些复杂的问题。
内核中的 cpufreq 子系统通过 sysfs 文件系统向上层应用提供了用户接口,对于系统中的每一个 CPU 而言,其 cpufreq 的 sysfs 用户接口位于 /sys/devices/system/cpu/cpuX/cpufreq/ 目录下,其中 X 代表 processor id ,与 /proc/cpuinfo 中的信息相对应。以cpu0 为例,用户一般会在该目录下观察到以下文件:
$ ls -F /sys/devices/system/cpu/cpu0/cpufreq/
affected_cpus
cpuinfo_cur_freq
cpuinfo_max_freq
2004-2006
Report errors and bugs to linux@brodo.de, please.
analyzing CPU 0:
driver: acpi-cpufreq
CPUs which need to switch frequency at the same time:
0 1
hardware limits: 1000 MHz - 1.67 GHz
available frequency steps: 1.67 GHz, 1.33 GHz, 1000
MHz
available cpufreq governors: userspace, conservative,
ondemand, powersave, performance
current policy: frequency should be within 1000 MHz
and 1.67 GHz.
The governor "ondemand" may decide which
speed to use
within this range.
current CPU frequency is 1000 MHz.
analyzing CPU 1:
driver: acpi-cpufreq
CPUs which need to switch frequency at the same time:
0 1
hardware limits: 1000 MHz - 1.67 GHz
available frequency steps: 1.67 GHz, 1.33 GHz, 1000
MHz
available cpufreq governors: userspace, conservative,
ondemand, powersave, performance
current policy: frequency should be within 1000 MHz
and 1.67 GHz.
The governor "ondemand" may decide which
speed to use
within this range.
current CPU frequency is 1000 MHz.