对Android设备CPU进行锁频

简介:

本文对Android设备CPU的状态查看方法和锁频(lock frequency)方法进行详细介绍。这有什么用?作为测试工程师,你值得了解。

CPU频率

首先说下CPU的频率。我们都知道,CPU的工作频率越高,运算就越快,但能耗也更高。然而很多时候,设备并不需要那么高的计算性能,这个时候,我们就希望能降低CPU的工作频率,追求较低的能耗,以此实现更长的待机时间。

基于此需求,当前电子设备的CPU都会存在多个工作频率,并能根据实际场景进行CPU频率的自动切换,以此达到平衡计算性能与能耗的目的。

锁频的用途

那么为什么需要锁频呢?

对于普通用户来说,可能对这些场景比较熟悉:

在家用笔记本电脑玩游戏的时候,电脑连着电源,不在乎能耗,只想要尽可能高的性能,这个时候就选择高性能模式,即保持CPU在最高频率工作。

旅行途中使用笔记本电脑,靠电池供电,希望电脑能待机尽可能久,这时就选择省电模式,即CPU保持在最低频率运行。

作为一名测试工程师,我们在进行软件测试的时候,为了让测试结果真实反映软件本身的效率,从控制变量法的角度,我们希望测试结果尽量不受到硬件本身的影响。这个时候,我们就可以尝试对设备的CPU进行锁频,即保证在测试的过程中,硬件设备的CPU运行在一个恒定的频率。

说到这里先埋个伏笔,在chromium官方测试库中,部分测试场景在初始化测试环境时,就会将设备所有CPU的频率调到最高状态,后续我会单独以一篇博客的形式对那部分的源码进行分析。对于等不及的朋友,可以先去看下源码,源码路径为pylib/perf/PerfControl.SetHighPerfMode。

查看CPU状态信息

在修改CPU的状态之前,我们需要先查看CPU的属性和状态信息,这样才能有针对性地进行正确的设置。

对于CPU的状态,我们通常会关注两类信息,一是整体层面的,即CPU运行的核数;二是细节层面的,即各个CPU的工作状态,包括所处工作模式、频率大小等。

在Android系统中,CPU相关的信息存储在/sys/devices/system/cpu目录的文件中,我们可以通过读取该目录下的特定文件获得当前设备的CPU状态信息,也可以通过对该目录下的特定文件进行写值,实现对CPU频率等状态信息的更改。

本文以Nexus 5(系统版本5.1.1)为例,后面的例子均以该设备为例。不同的机型和Android系统版本可能会存在一些差异,请知悉。

在/sys/devices/system/cpu目录中,文件结构如下所示。

 
 
  1. shell@hammerhead:/sys/devices/system/cpu $ ll 
  2.  
  3. drwxr-xr-x root     root              2016-01-20 01:36 cpu0 
  4.  
  5. drwxr-xr-x root     root              2016-01-20 21:06 cpu1 
  6.  
  7. drwxr-xr-x root     root              2016-01-20 21:07 cpu2 
  8.  
  9. drwxr-xr-x root     root              2016-01-20 21:07 cpu3 
  10.  
  11. -rw------- root     root         4096 1970-01-17 10:27 cpuctl 
  12.  
  13. drwxr-xr-x root     root              1970-01-17 10:27 cpufreq 
  14.  
  15. drwxr-xr-x root     root              1970-01-17 10:27 cpuidle 
  16.  
  17. -r--r--r-- root     root         4096 1970-01-17 10:27 kernel_max 
  18.  
  19. -r--r--r-- root     root         4096 1970-01-17 10:27 offline 
  20.  
  21. -r--r--r-- root     root         4096 1970-01-17 10:27 online 
  22.  
  23. -r--r--r-- root     root         4096 1970-01-17 10:27 possible 
  24.  
  25. drwxr-xr-x root     root              1970-01-17 10:27 power 
  26.  
  27. -r--r--r-- root     root         4096 1970-01-17 10:27 present 
  28.  
  29. -rw-r--r-- root     root         4096 1970-01-17 10:27 uevent 

1、view overall cpu info

在possible文件中,存储的是当前设备可用的CPU,显示形式以数字的形式。例如0-3代表的就是当前设备总共有4个核,编号分别为0,1,2,3。

 
 
  1. shell@hammerhead:/sys/devices/system/cpu $ cat possible 
  2.  
  3. 0-3 

在online文件中,存储的是当前设备正在运行的CPU。因为有时候设备不需要很高的性能,就可以将部分CPU关闭。不过需要注意的是,不管什么时候,CPU0始终都会处于运行状态。online文件的存储格式与possible类似,如果只有部分CPU运行,且CPU编号不连续的时候,会以逗号进行隔开;例如,0,2表示当前CPU0和CPU2处于运行状态。

 
 
  1. shell@hammerhead:/sys/devices/system/cpu $ cat online 
  2.  
  3. 0,2 

对应的,offline文件标示的是当前设备处于关闭状态的CPU,这和online作为互补,并集刚好就是设备的所有CPU,即possible文件中的内容。

 
 
  1. shell@hammerhead:/sys/devices/system/cpu $ cat offline 
  2.  
  3. 1,3 

2、view specified cpu info

接下来,我们要获取到特定CPU的信息,就需要进入到对应的文件夹,例如,cpu0/对应的就是CPU0的信息。

在/sys/devices/system/cpu/cpu0目录中,文件结构如下所示。

 
 
  1. shell@hammerhead:/sys/devices/system/cpu $ ll cpu0 
  2.  
  3. drwxr-xr-x root     root              2016-01-20 01:37 cpufreq 
  4.  
  5. drwxr-xr-x root     root              1970-01-17 10:27 cpuidle 
  6.  
  7. -r-------- root     root         4096 1970-01-17 10:27 crash_notes 
  8.  
  9. -rw-r--r-- root     root         4096 2016-01-20 01:36 online 
  10.  
  11. drwxr-xr-x root     root              1970-01-17 10:27 power 
  12.  
  13. drwxr-xr-x root     root              1970-01-17 10:27 rq-stats 
  14.  
  15. lrwxrwxrwx root     root              1970-01-17 10:27 subsystem 
  16.  
  17. drwxr-xr-x root     root              1970-01-17 10:27 topology 
  18.  
  19. -rw-r--r-- root     root         4096 1970-01-17 10:27 uevent 

其中,online文件的内容表示当前CPU是否处于运行状态,若处于运行状态,则内容为1,否则为0;这个和上面讲到的/sys/devices/system/cpu/online能进行对应。

 
 
  1. shell@hammerhead:/sys/devices/system/cpu $ cat cpu0/online 
  2.  

在cpu0/cpufreq/目录下,存储的就是与CPU0的频率相关的信息,文件结构如下所示。

 
 
  1. shell@hammerhead:/sys/devices/system/cpu $ ll cpu0/cpufreq/ 
  2.  
  3. -rw-r--r-- root     root         4096 2016-01-20 01:57 UV_mV_table 
  4.  
  5. -r--r--r-- root     root         4096 2016-01-20 01:57 affected_cpus 
  6.  
  7. -r--r--r-- root     root         4096 2016-01-20 01:57 cpu_utilization 
  8.  
  9. -r-------- root     root         4096 2016-01-20 01:57 cpuinfo_cur_freq 
  10.  
  11. -r--r--r-- root     root         4096 2016-01-20 02:00 cpuinfo_max_freq 
  12.  
  13. -r--r--r-- root     root         4096 2016-01-20 01:39 cpuinfo_min_freq 
  14.  
  15. -r--r--r-- root     root         4096 2016-01-20 01:57 cpuinfo_transition_latency 
  16.  
  17. -r--r--r-- root     root         4096 2016-01-20 01:57 related_cpus 
  18.  
  19. -r--r--r-- root     root         4096 2016-01-20 01:39 scaling_available_frequencies 
  20.  
  21. -r--r--r-- root     root         4096 2016-01-20 01:57 scaling_available_governors 
  22.  
  23. -r--r--r-- root     root         4096 2016-01-20 01:50 scaling_cur_freq 
  24.  
  25. -r--r--r-- root     root         4096 2016-01-20 01:57 scaling_driver 
  26.  
  27. -rw-r--r-- root     root         4096 2016-01-20 01:50 scaling_governor 
  28.  
  29. -rw-r--r-- root     root         4096 2016-01-20 08:29 scaling_max_freq 
  30.  
  31. -rw-r--r-- root     root         4096 2016-01-20 08:29 scaling_min_freq 
  32.  
  33. -rw-r--r-- root     root         4096 2016-01-20 02:52 scaling_setspeed 

在这个目录中,我们需要关注的文件比较多。

首先是scaling_available_governors和scaling_governor。这里的governor大家可以理解为CPU的工作模式,scaling_available_governors中存储了当前CPU支持的所有工作模式,而scaling_governor存储的是CPU当前所处的工作模式。

 
 
  1. shell@hammerhead:/sys/devices/system/cpu $ cat cpu0/cpufreq/scaling_available_governors 
  2.  
  3. impulse dancedance smartmax interactive conservative ondemand userspace powersave Lionheart bioshock performance 
  4.  
  5.   
  6.  
  7. shell@hammerhead:/sys/devices/system/cpu $ cat cpu0/cpufreq/scaling_governor 
  8.  
  9. performance 

可以看到,Nexus 5支持非常多的工作模式,这里只对几个常见的模式进行简单说明。

performance:最高性能模式,即使系统负载非常低,cpu也在最高频率下运行。

powersave:省电模式,与performance模式相反,cpu始终在最低频率下运行。

ondemand:CPU频率跟随系统负载进行变化。

userspace:可以简单理解为自定义模式,在该模式下可以对频率进行设定。

对于各种模式对应的含义和策略,在此不进行展开,大家有兴趣的可以自行搜索。

然后是CPU的工作频率范围,对应的文件有cpuinfo_max_freq、cpuinfo_min_freq、scaling_max_freq、scaling_min_freq。

以cpuinfo_为前缀的表示CPU硬件支持的频率范围,反映的是CPU自身的特性,与CPU的工作模式无关。而以scaling_为前缀的表示CPU在当前工作模式下的频率范围。

那么,当前CPU工作的频率是多少,我们要怎么查看呢?

查看cpuinfo_cur_freq或scaling_cur_freq即可。cpuinfo_cur_freq代表通过硬件实际上读到的频率值,而scaling_cur_freq则是软件当前的设置值,多数情况下这两个值是一致的,但是也有可能因为硬件的原因,有微小的差异。

 
 
  1. root@hammerhead:/sys/devices/system/cpu/cpu0/cpufreq # cat cpuinfo_cur_freq 
  2.  
  3. 1574400 
  4.  
  5. root@hammerhead:/sys/devices/system/cpu/cpu0/cpufreq # cat scaling_cur_freq 
  6.  
  7. 1574400 

更改CPU状态信息

最后回到我们本文的主题,如何对CPU的频率进行设定呢?

这也和CPU信息查看对应,分为对CPU整体运行情况的设置,和对特定CPU工作模式的设定。

在此,有两点需要特别进行说明。

首先,对于高通的CPU,存在一个系统服务,叫作mpdecision service。当这个系统服务处于运行状态时,我们无法对CPU的状态信息进行更改。因此,如果我们要更改高通CPU的工作模式,第一步要做的就是终止mpdecision系统服务。

操作起来也很简单,在Android shell里面执行如下命令即可。

 
 
  1. stop mpdecision 

第二点需要注意的是,如果我们想要实现对特定CPU的工作状态进行设置,就必须将scaling_governor设置为userspace,只有这样,我们才能对scaling_setspeed进行设置。

 
 
  1. root@hammerhead:/sys/devices/system/cpu/cpu0/cpufreq # cat scaling_setspeed       
  2.  
  3. root@hammerhead:/sys/devices/system/cpu/cpu0/cpufreq # echo userspace > scaling_governor 
  4.  
  5. root@hammerhead:/sys/devices/system/cpu/cpu0/cpufreq # cat scaling_setspeed     
  6.  
  7. 1574400 

1、set overall cpu info

从宏观层面,我们可以对CPU运行的核数进行设置,即可实现对特定CPU的开启和关闭。当然,我们在前面已经说过,CPU0始终会处于运行状态,因此我们无法将CPU0进行关闭。

设置的方式很简单,就是往/sys/devices/system/cpu/cpu[i]/online文件中写值即可,写1时开启指定CPU,写0时关闭指定CPU。

 
 
  1. # turn off cpu1 
  2.  
  3. root@hammerhead:/sys/devices/system/cpu/cpu1 # echo 0 > online 
  4.  
  5. root@hammerhead:/sys/devices/system/cpu/cpu1 # cat online 
  6.  

2、set specified cpu info

在对特定CPU的频率进行设定前,我们需要知道的是,CPU并不能工作在任意频率下,我们只能将CPU的频率设定为它支持的数值。

通过查看scaling_available_frequencies,我们可以获得当前CPU支持的频率值。

 
 
  1. root@hammerhead:/sys/devices/system/cpu/cpu0/cpufreq # cat scaling_available_frequencies 
  2.  
  3. 300000 422400 652800 729600 883200 960000 1036800 1190400 1267200 1497600 

接下来,我们就可以对CPU的工作频率进行设置了。

如何进行设置呢?刚开始的时候,我觉得将特定的频率值写入scaling_setspeed或scaling_cur_freq就可以了,通过Google搜索得到的方法中也是这种方式。

但经过尝试,发现并不可行。为什么会这样?我也还没有找到答案,希望知道原因的朋友能告诉我。

最后经过尝试,发现通过同时将scaling_max_freq和scaling_min_freq设置为目标频率值,就可以成功地对CPU频率完成设置。# before setting 

 
 
  1.  
  2. shell@hammerhead:/sys/devices/system/cpu/cpu0/cpufreq $ cat scaling_cur_freq 
  3.  
  4. 1574400      
  5.  
  6. # setting 
  7.  
  8. shell@hammerhead:/sys/devices/system/cpu/cpu0/cpufreq $ echo 1728000 > scaling_min_freq 
  9.  
  10. shell@hammerhead:/sys/devices/system/cpu/cpu0/cpufreq $ echo 1728000 > scaling_max_freq      
  11.  
  12. after setting 
  13.  
  14. shell@hammerhead:/sys/devices/system/cpu/cpu0/cpufreq $ cat scaling_cur_freq 
  15.  
  16. 1728000 






本文作者:佚名
来源:51CTO
目录
相关文章
|
2月前
|
Android开发 iOS开发 UED
探索未来:Android与iOS在智能穿戴设备上的较量
随着科技的飞速进步,智能穿戴设备已经成为我们日常生活中不可或缺的一部分。本文将深入探讨两大操作系统——Android和iOS——在智能穿戴领域的竞争与发展,分析它们各自的优势与挑战,并预测未来的发展趋势。通过比较两者在设计哲学、生态系统、用户体验及创新技术的应用等方面的差异,揭示这场较量对消费者选择和市场格局的影响。 【7月更文挑战第31天】
30 0
|
23天前
|
Shell Linux 开发工具
"开发者的救星:揭秘如何用adb神器征服Android设备,开启高效调试之旅!"
【8月更文挑战第20天】Android Debug Bridge (adb) 是 Android 开发者必备工具,用于实现计算机与 Android 设备间通讯,执行调试及命令操作。adb 提供了丰富的命令行接口,覆盖从基础设备管理到复杂系统操作的需求。本文详细介绍 adb 的安装配置流程,并列举实用命令示例,包括设备连接管理、应用安装调试、文件系统访问等基础功能,以及端口转发、日志查看等高级技巧。此外,还提供了常见问题的故障排除指南,帮助开发者快速解决问题。掌握 adb 将极大提升 Android 开发效率,助力项目顺利推进。
42 0
|
15天前
|
Android开发
基于Amlogic 安卓9.0, 驱动简说(四):Platform平台驱动,驱动与设备的分离
本文介绍了如何在基于Amlogic T972的Android 9.0系统上使用Platform平台驱动框架和设备树(DTS),实现设备与驱动的分离,并通过静态枚举在设备树中描述设备,自动触发驱动程序的加载和设备创建。
6 0
基于Amlogic 安卓9.0, 驱动简说(四):Platform平台驱动,驱动与设备的分离
|
15天前
|
Android开发 C语言
基于Amlogic 安卓9.0, 驱动简说(二):字符设备驱动,自动创建设备
这篇文章是关于如何在基于Amlogic T972的Android 9.0系统上,通过自动分配设备号和自动创建设备节点文件的方式,开发字符设备驱动程序的教程。
19 0
基于Amlogic 安卓9.0, 驱动简说(二):字符设备驱动,自动创建设备
|
15天前
|
自然语言处理 Shell Linux
基于Amlogic 安卓9.0, 驱动简说(一):字符设备驱动,手动创建设备
本文是关于在Amlogic安卓9.0平台上创建字符设备驱动的教程,详细介绍了驱动程序的编写、编译、部署和测试过程,并提供了完整的源码和应用层调用示例。
32 0
基于Amlogic 安卓9.0, 驱动简说(一):字符设备驱动,手动创建设备
|
15天前
|
传感器 Android开发 芯片
不写一行代码(三):实现安卓基于i2c bus的Slaver设备驱动
本文是系列文章的第三篇,展示了如何在Android系统中利用现有的i2c bus驱动,通过编写设备树节点和应用层的控制代码,实现对基于i2c bus的Slaver设备(如六轴陀螺仪模块QMI8658C)的控制,而无需编写设备驱动代码。
26 0
不写一行代码(三):实现安卓基于i2c bus的Slaver设备驱动
|
15天前
|
Android开发
不写一行代码(二):实现安卓基于PWM的LED设备驱动
本文介绍了在Android系统中不编写任何代码,通过设备树配置和内核支持的通用PWM LED驱动来实现基于PWM的LED设备驱动,并通过测试命令调整LED亮度级别。
24 0
不写一行代码(二):实现安卓基于PWM的LED设备驱动
|
15天前
|
Linux Android开发 C语言
不写一行代码(一):实现安卓基于GPIO的LED设备驱动
本文通过实践操作,展示了在Android系统中不编写任何代码,利用设备树(DTS)配置和内核支持的通用GPIO LED驱动来控制LED设备,并进一步通过C语言编写NDK测试APP来实现LED的闪烁效果。
29 0
不写一行代码(一):实现安卓基于GPIO的LED设备驱动
|
1月前
|
Android开发 开发者
Android、Flutter为不同的CPU架构包打包APK(v7a、v8a、x86)
Android、Flutter为不同的CPU架构包打包APK(v7a、v8a、x86)
43 1
|
28天前
|
存储 Ubuntu API
如何使用Python创建服务器向Android设备发送GCM推送通知
如何使用Python创建服务器向Android设备发送GCM推送通知
11 0