新闻中心

EEPW首页 > 电源与新能源 > 设计应用 > Linux 2.6 内核中的最新电源管理技术综述

Linux 2.6 内核中的最新电源管理技术综述

作者:时间:2008-07-18来源:网络收藏
前言

本系列文章将结合近年来不断在各种硬件(包括CPU、芯片组、PCIExpress等各种总线标准以及外设)上新增的节能,从®及整个softwarestack(包括kernel、middleware以及各种用户态utility)如何添加对这些创新的节能的支持这一角度,为读者介绍操作系统近几年来在方面所取得的长足进步以及未来的发展方向。

作为本系列文章的开篇之作,首先要向大家介绍的是cpufreq,它是为了更好的支持近年来在各款主流CPU处理器中出现的变频而新增的一个子系统。

Cpufreq的由来

随着energyefficientcomputing和performanceperwatt等概念的推广以及高级配置与接口ACPI(AdvancedConfigurationandPowerInterface)标准的发展,目前市场上的主流CPU都提供了对变频(frequencyscaling)技术的支持。例如Intel®处理器所支持的EnhancedSpeedStep®技术和AMD®处理器所支持的PowerNow!®技术,另外像的PowerPC®、ARM®、SPARC®和SuperH®等处理器中也提供了类似的支持。参考资料中列出了当前Linux内核所支持的具备变频技术的处理器。需要注意的是,这里要讨论的变频技术与大家以前所熟知的超频是两个不同的概念。超频是指通过提高核心电压等手段让处理器工作在非标准频率下的行为,这往往会造成CPU使用寿命缩短以及系统稳定性下降等严重后果。而变频技术是指CPU硬件本身支持在不同的频率下运行,系统在运行过程中可以根据随时可能发生变化的系统负载情况动态在这些不同的运行频率之间进行切换,从而达到对性能和功耗做到二者兼顾的目的。

虽然多个处理器生产厂家都提供了对变频技术的支持,但是其硬件实现和使用方法必然存在着细微甚至巨大的差别。这就使得每个处理器生产厂家都需要按照其特殊的硬件实现和使用方法向内核中添加代码,从而让自己产品中的变频技术在Linux中得到支持和使用。然而,这种内核开发模式所导致的后果是各个厂家的实现代码散落在Linux内核代码树的各个角落里,各种不同的实现之间没有任何代码是共享的,这给内核的维护以及将来添加对新的产品的支持都带来了巨大的开销,并直接导致了cpufreq内核子系统的诞生。实际上,正如前文所说,发明变频技术的目的是为了能够让系统在运行过程中随时根据系统负载的变化动态调整CPU的运行频率。这件事情可以分为两个部分,一部分是“做什么”的问题,另一部分是“怎么做”的问题。“做什么”是指如何根据系统负载的动态变化挑选出CPU合适的运行频率,而“怎么做”就是要按照选定的运行频率在选定的时间对CPU进行设置,使之真正工作在这一频率上。这也就是我们在软件设计中经常会遇到的机制mechanism与策略policy的问题,而设计良好的软件会在架构上保证二者是被清晰的隔离开的并通过规范定义的接口进行通信。

Cpufreq的设计和使用

为了解决前文所提到的问题,一个新的内核子系统――cpufreq应运而生了。Cpufreq为在Linux内核中更好的支持不同CPU的变频技术提供了一个统一的设计框架,其软件结构如图1所示。
图 1. Cpufreq 的软件结构

如图 1 所示,cpufreq 在设计上主要分为以下三个模块:

Cpufreq模块(cpufreqmodule)对如何在底层控制各种不同CPU所支持的变频技术以及如何在上层根据系统负载动态选择合适的运行频率进行了封装和抽象,并在二者之间定义了清晰的接口,从而在设计上完成了前文所提到的对mechanism与policy的分离。
在cpufreq模块的底层,各个CPU生产厂商只需根据其变频技术的硬件实现和使用方法提供与其CPU相关的变频驱动程序(CPU-specificdrivers),例如Intel需要提供支持EnhancedSpeedStep技术的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代表processorid,与/proc/cpuinfo中的信息相对应。以cpu0为例,用户一般会在该目录下观察到以下文件:

$ls-F/sys/devices/system/cpu/cpu0/cpufreq/
affected_cpus
cpuinfo_cur_freq
cpuinfo_max_freq

cpuinfo_min_freq
ondemand/
scaling_available_frequencies
scaling_available_governors
scaling_cur_freq
scaling_driver
scaling_governor
scaling_max_freq
scaling_min_freq
stats/



这其中的所有可读文件都可以使用cat命令进行读操作,另外所有可写文件都可以使用echo命令进行写操作。其中cpuinfo_max_freq和cpuinfo_min_freq分别给出了CPU硬件所支持的最高运行频率及最低运行频率,cpuinfo_cur_freq则会从CPU硬件寄存器中读取CPU当前所处的运行频率。虽然CPU硬件支持多种不同的运行频率,但是在有些场合下用户可以只选择使用其中的一个子集,这种控制是通过scaling_max_freq和scaling_min_freq进行的。Governor在选择合适的运行频率时只会在scaling_max_freq和scaling_min_freq所确定的频率范围内进行选择,这也就是scaling_available_frequencies所显示的内容。与cpuinfo_cur_freq不同,scaling_cur_freq返回的是cpufreq模块缓存的CPU当前运行频率,而不会对CPU硬件寄存器进行检查。scaling_available_governors会告诉用户当前有哪些governors可供用户使用,而scaling_driver则会显示该CPU所使用的变频驱动程序。Stats目录下给出了对CPU各种运行频率的使用统计情况,例如CPU在各种频率下的运行时间以及在各种频率之间的变频次数。Ondemand目录则与ondemandgovernor相关,在后文会进行相应的介绍。

通过以上的介绍,大家对如何使用cpufreq通过sysfs提供的用户接口已经有了大致的了解,但是对于绝大部分用户而言,逐一操作这些文件既费力又耗时。因此Dominik等人开发了cpufrequtils工具包[2],为用户提供了更加简便的对内核cpufreq子系统的操作接口。通过cpufreq-info的输出,读者可以很清楚的看到刚刚在上面介绍过的/sys/devices/system/cpu/cpuX/cpufreq/目录下各个文件的内容。

$cpufreq-info
cpufrequtils002:cpufreq-info(C)DominikBrodowski2004-2006
Reporterrorsandbugstolinux@brodo.de,please.
analyzingCPU0:
driver:acpi-cpufreq
CPUswhichneedtoswitchfrequencyatthesametime:01
hardwarelimits:1000MHz-1.67GHz
availablefrequencysteps:1.67GHz,1.33GHz,1000MHz
availablecpufreqgovernors:userspace,conservative,ondemand,powersave,performance
currentpolicy:frequencyshouldbewithin1000MHzand1.67GHz.
Thegovernor"ondemand"maydecidewhichspeedtouse
withinthisrange.
currentCPUfrequencyis1000MHz.
analyzingCPU1:
driver:acpi-cpufreq
CPUswhichneedtoswitchfrequencyatthesametime:01
hardwarelimits:1000MHz-1.67GHz
availablefrequencysteps:1.67GHz,1.33GHz,1000MHz
availablecpufreqgovernors:userspace,conservative,ondemand,powersave,performance
currentpolicy:frequencyshouldbewithin1000MHzand1.67GHz.
Thegovernor"ondemand"maydecidewhichspeedtouse
withinthisrange.
currentCPUfrequencyis1000MHz.


Ondemandgovernor的由来及其实现

刚刚我们在cpufreq-info的输出中可以看到cpufreq子系统一共提供了五种governors供用户选择使用,它们分别是userspace,conservative,ondemand,powersave和performance。在最新的内核中如果用户不进行额外设置的话,ondemand会被作为默认的governor使用。为了理解是什么原因造成了这种现状,我们在这里带领读者回顾一下cpufreq子系统中的governor在内核中的开发历史。

Cpufreq作为一个子系统最早被加入到Linux内核中时只配备了三个governors,分别是performance、powersave和userspace。当用户选择使用performancegovernor时,CPU会固定工作在其支持的最高运行频率上;当用户选择使用powersavegovernor时,CPU会固定工作在其支持的最低运行频率上。因此这两种governors都属于静态governor,即在使用它们时CPU的运行频率不会根据系统运行时负载的变化动态作出调整。这两种governors对应的是两种极端的应用场景,使用performancegovernor体现的是对系统高性能的最大追求,而使用powersavegovernor则是对系统低功耗的最大追求。虽然这两种应用需求确实存在,但大多数用户在大部分时间里需要的是更加灵活的变频策略。最早的cpufreq子系统通过userspacegovernor为用户提供了这种灵活性。正如它的名字一样,使用userspacegovernor时,系统将变频策略的决策权交给了用户态应用程序,并提供了相应的接口供用户态应用程序调节CPU运行频率使用。通过使用cpufrequtils工具包中的cpufreq-set将userspace设置为cpufreq子系统所使用的governor后,我们可以看到与之前相比在/sys/devices/system/cpu/cpuX/cpufreq/目录下多出了一个名为scaling_setspeed的文件,这正是userspacegovernor所提供的特殊用户接口。用户可以通过向该文件写入任何一个scaling_available_frequencies中所支持的运行频率,从而将CPU设置在该频率下运行。

#cpufreq-set-guserspace
#catcpuinfo_cur_freq
1000000
#catscaling_available_frequencies
166700013330001000000
#echo1333000>scaling_setspeed
#catcpuinfo_cur_freq
1333000



刚刚提到在使用userspacegovernor时,系统将变频策略的决策权交给了用户态应用程序。该用户态应用程序一般是一个daemon程序,每隔一定的时间间隔收集一次系统信息并根据系统的负载情况使用userspacegovernor提供的scaling_setspeed接口动态调整CPU的运行频率。作为这个daemon程序,当时在几个主要的Linux发行版中使用的一般是powersaved或者cpuspeed。这两个daemon程序一般每隔几秒钟统计一次CPU在这个采样周期内的负载情况,并根据统计结果调整CPU的运行频率。这种userspacegovernor加用户态daemon程序的变频方法虽然为用户提供了一定的灵活性,但通过开源社区的广泛使用所得到的意见反馈逐渐暴露了这种方法的两个严重缺陷。第一个是性能方面的问题。例如powersaved每隔五秒钟进行一次系统负载情况的采样分析的话,我们可以分析一下在下面给出的应用场景中的用户体验。假设powersaved的采样分析刚刚结束,而且由于在刚刚结束的采样周期内系统负载很低,CPU被设置在最低频率上运行。这时用户如果打开Firefox®等对CPU运算能力要求相当高的程序的话,powersaved要在下一个采样点――大约五秒钟之后才有机会观察到这种提高CPU运行频率的需求。也就是说,在Firefox启动之初的五秒钟内CPU的计算能力并没有被充分发挥出来,这无疑会使用户体验大打折扣。第二个是系统负载情况的采样分析的准确性问题。将监控系统负载情况并对未来CPU的性能需求做出判断的任务交给一个用户态程序完成实际上并不合理,一方面是由于一个用户态程序很难完整的收集到所有需要的信息,因为这些信息大部分都保存在内核空间;另一方面一个用户态程序如果想要收集这些系统信息,必然需要进行用户态与内核态之间的数据交互,而频繁的用户态与内核态之间的数据交互又会给系统性能带来负面影响。

那么这两个问题有没有解决的方法呢?应该讲社区中的开发人员就第二个问题比较容易达成一致,既然在用户态对系统的负载情况进行采集和分析存在这样那样的问题,那么更加合理的做法就是应该将这部分工作交由内核负责。但是第一个问题呢?第一个问题最直观的解决方案就是降低对系统负载进行采样分析的时间间隔,这样powersaved就能尽早的对系统负载的变化做出及时的响应。然而这种简单的降低采样分析的时间间隔的方案同样存在着两方面的问题,一方面这意味着更加频繁的用户态与内核态之间的数据交互,因此必然也就意味着对系统性能带来更大的负面影响;另一方面的主要原因在于当时各个CPU生产厂家的变频技术在硬件上仍不完善,具体体现就是在对CPU进行变频设置时所需的操作时间过长,例如Intel早期的Speedstep技术在对CPU进行变频设置时需要耗时250微秒,在此过程中CPU无法正常执行指令。读者如果简单的计算一下不难发现,即使对于一个主频为1GHz的CPU而言,250微秒也意味着250,000个时钟周期,在这期间CPU完全可以执行完上万条指令。因此从这个角度而言,简单的降低采样分析的时间间隔对系统性能带来的负面影响更加严重。幸运的是随着硬件技术的不断完善和改进,对CPU进行变频设置所需的操作时间已经显著降低,例如Intel最新的EnhancedSpeedstep技术在对CPU进行变频设置时耗时已降至10微秒,下降了不止一个数量级。正是这种CPU硬件技术的发展为内核开发人员解决这些早期的遗留问题提供了契机,Venkatesh等人提出并设计实现了一个新的名为ondemand的governor,它正是人们长期以来希望看到的一个完全在内核态下工作并且能够以更加细粒度的时间间隔对系统负载情况进行采样分析的governor。在介绍ondemandgovernor的具体实现之前,我们先来看一下如何使用ondemandgovernor及其向用户提供了哪些操作接口。通过cpufreq-set将ondemand设置为当前所使用的governor之后,在/sys/devices/system/cpu/cpuX/cpufreq目录下会出现一个名为ondemand的子目录

$sudocpufreq-set-gondemand
$ls/sys/devices/system/cpu/cpu0/cpufreq/ondemand/
ignore_nice_load
powersave_bias
sampling_rate
sampling_rate_max
sampling_rate_min
up_threshold
$sudocatsampling_rate_minsampling_ratesampling_rate_max
40000
80000
40000000
$sudocatup_threshold
30



在这个子目录下名字以sampling打头的三个文件分别给出了ondemandgovernor允许使用的最短采样间隔,当前使用的采样间隔以及允许使用的最长采样间隔,三者均以微秒为单位。以笔者的电脑为例,ondemandgovernor每隔80毫秒进行一次采样。另外比较重要的一个文件是up_threshold,它表明了系统负载超过什么百分比时ondemandgovernor会自动提高CPU的运行频率。以笔者的电脑为例,这个数值为30%。那么这个表明系统负载的百分比数值是如何得到的呢?在支持Intel最新的EnhancedSpeedstep技术的CPU中,在处理器硬件中直接提供了两个MSR寄存器(ModelSpecificRegister)供ondemandgovernor采样分析系统负载情况使用。这两个MSR寄存器的名字分别为IA32_MPERF和IA32_APERF[5],其中IA32_MPERFMSR中的MPERF代表MaximumPerformance,IA32_APERFMSR中的APERF代表ActualPerformance。就像这两个MSR的名字一样,IA32_MPERFMSR寄存器是一个当CPU处在ACPIC0状态下时按照CPU硬件支持的最高运行频率每隔一个时钟周期加一的计数器;IA32_APERFMSR寄存器是一个当CPU处在ACPIC0状态下时按照CPU硬件当前的实际运行频率每隔一个时钟周期加一的计数器。有了这两个寄存器的存在,再考虑上CPU处于ACPIC0和处于ACPIC1、C2、C3三种状态下的时间比例,也就是CPU处于工作状态和休眠状态的时间比例,ondemandgovernor就可以准确的计算出CPU的负载情况了。

得到了CPU的负载情况,接下来的问题就是如何选择CPU合适的运行频率了。刚刚在前面提到,当系统负载超过up_threshold所设定的百分比时,ondemandgovernor将会自动提高CPU的运行频率,但是具体提高到哪个频率上运行呢?在ondemandgovernor监测到系统负载超过up_threshold所设定的百分比时,说明用户当前需要CPU提供更强大的处理能力,因此ondemandgovernor会将CPU设置在最高频率上运行,这一点社区中的开发人员和广大用户都没有任何异议。但是当ondemandgovernor监测到系统负载下降,可以降低CPU的运行频率时,到底应该降低到哪个频率呢?ondemandgovernor的最初实现是在可选的频率范围内调低至下一个可用频率,例如笔者使用的CPU支持三个可选频率,分别为1.67GHz、1.33GHz和1GHz,如果CPU运行在1.67GHz时ondemandgovernor发现可以降低运行频率,那么1.33GHz将被选作降频的目标频率。这种降频策略的主导思想是尽量减小对系统性能的负面影响,从而不会使得系统性能在短时间内迅速降低以影响用户体验。但是在ondemandgovernor的这种最初实现版本在社区发布后,大量用户的使用结果表明这种担心实际上是多余的,ondemandgovernor在降频时对于目标频率的选择完全可以更加激进。因此最新的ondemandgovernor在降频时会在所有可选频率中一次性选择出可以保证CPU工作在80%以上负荷的频率,当然如果没有任何一个可选频率满足要求的话则会选择CPU支持的最低运行频率。大量用户的测试结果表明这种新的算法可以在不影响系统性能的前提下做到更高效的节能。在算法改进后,ondemandgovernor的名字并没有改变,而ondemandgovernor最初的实现也保存了下来,并且由于其算法的保守性而得名conservative。


支持IntelEnhancedSpeedstep技术的CPU驱动程序的实现

前文在讨论cpufreq的软件结构时已经指出,cpufreq从设计上将CPU变频的policy与mechanism分离开来并由上层的governor负责决定CPU合适的工作频率。但是在governor根据系统负载的变化决定调整CPU的运行频率时,最终还是需要底层与CPU相关的特定驱动程序完成设置CPU运行频率的任务。这里向读者介绍一下支持Intel最新的EnhancedSpeedstep技术的CPU驱动程序的实现原理,关注的重点是如何对CPU进行变频设置。实际上支持IntelEnhancedSpeedstep技术的处理器为用户提供了非常简单的编程接口,对CPU运行频率进行设置是通过一个名为IA32_PERF_CTL的MSR寄存器进行的,另外还有一个名为IA32_PERF_STATUS的MSR寄存器可供检查CPU当前所处的运行频率。当用户需要对CPU运行频率进行设置时只需按照Intel开发手册的说明向IA32_PERF_CTLMSR寄存器中写入规定的数值即可。

总结及未来的发展方向

本文为读者介绍了变频技术在CPU硬件上的出现以及Linux内核中最初的实现存在的各种问题,并由此导致了cpufreq这一新的内核子系统的诞生。虽然早期的cpufreq模块所提供的三种governors能够在一定程度下满足用户的需要并且提供了一定的灵活性,但是由于受到当时CPU硬件技术水平的限制,仍然有很多不尽如人意的地方。之后随着CPU变频硬件技术的不断发展,尤其是IntelEnhancedSpeedstep技术的出现,原有的技术障碍被打破,随之而来的是cpufreq内核子系统有了一个全新的更加完善而高效的ondemandgovernor。

由此不难看出,内核中的cpufreq子系统是由于CPU硬件变频技术的出现而出现,同时也在随着CPU硬件变频技术的发展而发展。这其实也预示着内核中cpufreq子系统未来的发展方向,即继续跟随CPU硬件变频技术的发展脚步与时俱进。在本文的最后简单为读者介绍一下在Intel最新的CPU中针对硬件变频支持的一项新技术。前文提到在支持Intel最新的EnhancedSpeedstep技术的CPU中提供了名字分别为IA32_MPERF和IA32_APERF的两个MSR寄存器,以便为cpufreq模块所使用的governor动态收集系统的负载情况提供直接的硬件支持。其中IA32_APERFMSR寄存器当CPU处在ACPIC0状态下时按照CPU硬件当前的实际运行频率每隔一个时钟周期加一。Intel最新的处理器中进一步考虑了CPU在运行过程中由于访问内存或IO等原因可能会出现流水线停摆的状况时,IA32_APERF以前这种简单的按照CPU当前实际运行频率每隔一个时钟周期加一的做法并不能完全准确的反映CPU的负载情况。在Intel最新的处理器中如果出现流水线停摆的情况,IA32_APERF将暂时停止累加,而是在对用户真正“有用”的时间周期才会递增,这样CPU硬件就可以为cpufreq模块所使用的governor提供比以前更加准确的系统负载统计信息。

linux操作系统文章专题:linux操作系统详解(linux不再难懂)


评论


相关推荐

技术专区

关闭