powersave/performance governor study
2013-11-27 15:44
411 查看
这个governor是最省电模式,即cpu中所有的core都处在最低频率运行。如果是存在cpu hotplug driver的话,那么还可以更加的省电,即只存在一个core是online状态的,关掉其他的core。
废话不多说,直接讲解code:
1、static int __init cpufreq_gov_powersave_init(void)
这是注册powersave governor driver,很简单,直接返回一条注册语句。函数原型是:
int cpufreq_register_governor(struct cpufreq_governor *governor)。
其中,cpufreq_governor结构体的原型如下:
各个元素含义如下:
1、char name[CPUFREQ_NAME_LEN]:是此governor的name。
2、 int (*governor) (structcpufreq_policy *policy,unsigned int event):是对此governor进行初始化的操作的回调函数。
3、ssize_t (*show_setspeed) (structcpufreq_policy *policy,char *buf):显示当前修改的频率值。
4、int (*store_setspeed) (structcpufreq_policy *policy,unsigned int freq):这个函数只有userspacegovernor使用,是可以对当前的cpu频率进行手动的调整。
5、unsignedint max_transition_latency:最大转换时延,即频率切换所能够忍受的最大延迟。
6、structlist_head governor_list:一个链表,存放的是这个结构体的信息。在各个governor中没有使用到。
7、structmodule *owner:模块的拥有者。
在powersave和performance这两个governor只会对name/governor/owner这三个元素进行设置,由于不需要进行频率的切换,所以也就无需关心频率转换时延和频率的变化了。
我们看看这个结构体在这个governor中是怎样定义的:
设置的一目了然。
现在来看看这个回调函数:cpufreq_governor_powersave了。
code如下:
由于powersave和performance governor仅仅只需对频率进行固定性的设置,所以在这个回调函数中,event是CPUFREQ_GOV_START和CPUFREQ_GOV_LIMITS无关紧要了,本来event是CPUFREQ_GOV_START时,是对这个governor进行初始化工作的,比如频率转换时延的设置,抽样速率的设置(不固定),定时器的初始化,sys接口的设置等等动作,不过这些只有interactive、ondemand和conservative governor才会设置,这是后话。而event为CPUFREQ_GOV_LIMITS时是执行频率的转化操作,通过这个函数实现:
__cpufreq_driver_target(policy, policy->min,CPUFREQ_RELATION_L)
如果event是CPUFREQ_GOV_STOP的话,操作是与event为CPUFREQ_GOV_START相反的操作,如sys接口的卸载,定时器的删除等等操作。现在在poswersave governor中只需要关心这个调节频率的函数__cpufreq_driver_target的工作原理是怎样实现的。
函数的code如下,在cpufreq.c中定义的:
主要是第二个if语句中cpufreq_driver->target(policy,target_freq, relation);它是怎样动作的才是最重要的。
if(cpu_online(policy->cpu) && cpufreq_driver->target)
首先判断当前的cpu是否online状态,即活着,没有plugout,否则也就没有意义了;cpufreq_driver->target这是一个回调函数真正执行具体调频的函数。
那么现在就来看看两个非常重要的结构体:
这个结构体里面的各个元素解释的非常清楚,无需多讲。其实就是与每一个cpu core相关连的policy,即相应的cpu core 采用的governor的限制条件的组合。
下面这个结构体是真实调频driver的使用的结构体,里面包含了很多个回调函数,这些回调函数一些必不可少的会在driver中实现。
执行cpu频率调整的函数,由相应体系结构的cpufrequency具体driver负责。在我的电脑上是使用的driver是:/driver/cpufreq/acpi-cpufreq.c中。你可以到你源码目录下查找。更可靠的方式是在linux电脑上这个目录下查找:
cat /sys/devices/system/cpu/cpu0/cpufreq/scaling_driver 出的数据,就是你真正使用的driver了。
我的电脑显示的是:
root@samarxie:/sys/devices/system/cpu/cpu0/cpufreq# cat scaling_driver
acpi-cpufreq
这个回调函数是一定定义了的,可以放心使用。
如在我的电脑上,acpi-coufreq.c中对这个结构体的实现:
讲讲这个结构体中重要的几个元素的含义:
1、verify:是验证工作,目的验证当前的cpu的频率是否在限制范围内。用法如下: cpufreq_driver->verify(policy)
2、target:执行调频动作。
3、bios_limit:在bios中限制的cpu的频率范围。
4、init:初始化工作。
5、resume和suspend在power management中使用。
至此两个最重要的结构体完成了,其实我自己还是有些混乱的。呵呵。。。
继续回到执行调节频率的位置,在powersave governor中: __cpufreq_driver_target(policy, policy->min, CPUFREQ_RELATION_L),目的是使所有online状态的cpu处在最低频率运行。这里又涉及到一个有意思的参数relation。
relation只有两种值:CPUFREQ_RELATION_H和CPUFREQ_RELATION_L。
看看kernel的定义:
#define CPUFREQ_RELATION_L 0 /* lowest frequency at or above target ,查找大于等于其频率的最小频率*/
#define CPUFREQ_RELATION_H 1 /* highest frequency below or at target ,查找小于等于其频率的最大频率*/
这两个参数用的非常的频繁,主要用在cpufreq table中,用来查找合适的频率。当然对于powersave和performance governor是使用不到的。
cpufreq table是一个频率档,cpu的频率可以在这里面进行升降根据当前的cpu load。至于怎么分的,可以
cat /sys/devices/system/cpu/cpu0/cpufreq/scaling_available_frequencies,会显示当前电脑分了多少档。
cat /sys/devices/system/cpu/cpu0/cpufreq/stats/trans_table,这是一个统计表格,统计各个频率档使用的次数,
在调整过程中调到此频率的次数(个人理解)。
由于是powersave governor,所以当relation是CPUFREQ_RELATION_L的时候,查找>=policy->min的频率,最后找到的还是最小频率。
对于performance governor与powersave governor是类似的,仅仅做了两处改动:
1、
name修改了。
2、 __cpufreq_driver_target(policy, policy->max,CPUFREQ_RELATION_H);这个调节频率的函数修改。思想是一样,只不过换成了调整为最高频率。
由于第一次发这种帖子,估计有很多不足。原来真的是要自己看懂的写出来和说出来是另外一回事,希望这篇文章不要误导了其他人,如果有,我先说声sorry。~_~.
废话不多说,直接讲解code:
1、static int __init cpufreq_gov_powersave_init(void)
static int __init cpufreq_gov_powersave_init(void) { return cpufreq_register_governor(&cpufreq_gov_powersave); }
这是注册powersave governor driver,很简单,直接返回一条注册语句。函数原型是:
int cpufreq_register_governor(struct cpufreq_governor *governor)。
其中,cpufreq_governor结构体的原型如下:
struct cpufreq_governor { char name[CPUFREQ_NAME_LEN]; int (*governor) (struct cpufreq_policy *policy, unsigned int event); ssize_t (*show_setspeed) (struct cpufreq_policy *policy, char *buf); int (*store_setspeed) (struct cpufreq_policy *policy, unsigned int freq); unsigned int max_transition_latency; /* HW must be able to switch to next freq faster than this value in nano secs or we will fallback to performance governor */ struct list_head governor_list; struct module *owner; };
各个元素含义如下:
1、char name[CPUFREQ_NAME_LEN]:是此governor的name。
2、 int (*governor) (structcpufreq_policy *policy,unsigned int event):是对此governor进行初始化的操作的回调函数。
3、ssize_t (*show_setspeed) (structcpufreq_policy *policy,char *buf):显示当前修改的频率值。
4、int (*store_setspeed) (structcpufreq_policy *policy,unsigned int freq):这个函数只有userspacegovernor使用,是可以对当前的cpu频率进行手动的调整。
5、unsignedint max_transition_latency:最大转换时延,即频率切换所能够忍受的最大延迟。
6、structlist_head governor_list:一个链表,存放的是这个结构体的信息。在各个governor中没有使用到。
7、structmodule *owner:模块的拥有者。
在powersave和performance这两个governor只会对name/governor/owner这三个元素进行设置,由于不需要进行频率的切换,所以也就无需关心频率转换时延和频率的变化了。
我们看看这个结构体在这个governor中是怎样定义的:
struct cpufreq_governor cpufreq_gov_powersave = { .name = "powersave", .governor = cpufreq_governor_powersave, .owner = THIS_MODULE, };
设置的一目了然。
现在来看看这个回调函数:cpufreq_governor_powersave了。
code如下:
static int cpufreq_governor_powersave(struct cpufreq_policy *policy, unsigned int event) { switch (event) { case CPUFREQ_GOV_START: case CPUFREQ_GOV_LIMITS: pr_debug("setting to %u kHz because of event %u\n", policy->min, event); __cpufreq_driver_target(policy, policy->min, CPUFREQ_RELATION_L); break; default: break; } return 0; }
由于powersave和performance governor仅仅只需对频率进行固定性的设置,所以在这个回调函数中,event是CPUFREQ_GOV_START和CPUFREQ_GOV_LIMITS无关紧要了,本来event是CPUFREQ_GOV_START时,是对这个governor进行初始化工作的,比如频率转换时延的设置,抽样速率的设置(不固定),定时器的初始化,sys接口的设置等等动作,不过这些只有interactive、ondemand和conservative governor才会设置,这是后话。而event为CPUFREQ_GOV_LIMITS时是执行频率的转化操作,通过这个函数实现:
__cpufreq_driver_target(policy, policy->min,CPUFREQ_RELATION_L)
如果event是CPUFREQ_GOV_STOP的话,操作是与event为CPUFREQ_GOV_START相反的操作,如sys接口的卸载,定时器的删除等等操作。现在在poswersave governor中只需要关心这个调节频率的函数__cpufreq_driver_target的工作原理是怎样实现的。
函数的code如下,在cpufreq.c中定义的:
int __cpufreq_driver_target(struct cpufreq_policy *policy, unsigned int target_freq, unsigned int relation) { int retval = -EINVAL; if (cpufreq_disabled()) return -ENODEV; pr_debug("target for CPU %u: %u kHz, relation %u\n", policy->cpu, target_freq, relation); if (cpu_online(policy->cpu) && cpufreq_driver->target) retval = cpufreq_driver->target(policy, target_freq, relation); return retval; }
主要是第二个if语句中cpufreq_driver->target(policy,target_freq, relation);它是怎样动作的才是最重要的。
if(cpu_online(policy->cpu) && cpufreq_driver->target)
首先判断当前的cpu是否online状态,即活着,没有plugout,否则也就没有意义了;cpufreq_driver->target这是一个回调函数真正执行具体调频的函数。
那么现在就来看看两个非常重要的结构体:
struct cpufreq_policy { cpumask_var_t cpus; /* CPUs requiring sw coordination */ cpumask_var_t related_cpus; /* CPUs with any coordination */ unsigned int shared_type; /* ANY or ALL affected CPUs should set cpufreq */ unsigned int cpu; /* cpu nr of registered CPU */ struct cpufreq_cpuinfo cpuinfo;/* see above */ unsigned int min; /* in kHz */ unsigned int max; /* in kHz */ unsigned int cur; /* in kHz, only needed if cpufreq * governors are used */ unsigned int policy; /* see above */ struct cpufreq_governor *governor; /* see below */ struct work_struct update; /* if update_policy() needs to be * called, but you're in IRQ context */ struct cpufreq_real_policy user_policy; struct kobject kobj; struct completion kobj_unregister; };
这个结构体里面的各个元素解释的非常清楚,无需多讲。其实就是与每一个cpu core相关连的policy,即相应的cpu core 采用的governor的限制条件的组合。
下面这个结构体是真实调频driver的使用的结构体,里面包含了很多个回调函数,这些回调函数一些必不可少的会在driver中实现。
struct cpufreq_driver { struct module *owner; char name[CPUFREQ_NAME_LEN]; u8 flags; /* needed by all drivers */ int (*init) (struct cpufreq_policy *policy); int (*verify) (struct cpufreq_policy *policy); /* define one out of two */ int (*setpolicy) (struct cpufreq_policy *policy); int (*target) (struct cpufreq_policy *policy, unsigned int target_freq, unsigned int relation); /* should be defined, if possible */ unsigned int (*get) (unsigned int cpu); /* optional */ unsigned int (*getavg) (struct cpufreq_policy *policy, unsigned int cpu); int (*bios_limit) (int cpu, unsigned int *limit); int (*exit) (struct cpufreq_policy *policy); int (*suspend) (struct cpufreq_policy *policy); int (*resume) (struct cpufreq_policy *policy); struct freq_attr **attr; };
执行cpu频率调整的函数,由相应体系结构的cpufrequency具体driver负责。在我的电脑上是使用的driver是:/driver/cpufreq/acpi-cpufreq.c中。你可以到你源码目录下查找。更可靠的方式是在linux电脑上这个目录下查找:
cat /sys/devices/system/cpu/cpu0/cpufreq/scaling_driver 出的数据,就是你真正使用的driver了。
我的电脑显示的是:
root@samarxie:/sys/devices/system/cpu/cpu0/cpufreq# cat scaling_driver
acpi-cpufreq
这个回调函数是一定定义了的,可以放心使用。
如在我的电脑上,acpi-coufreq.c中对这个结构体的实现:
static struct cpufreq_driver acpi_cpufreq_driver = { .verify = acpi_cpufreq_verify, .target = acpi_cpufreq_target, .bios_limit = acpi_processor_get_bios_limit, .init = acpi_cpufreq_cpu_init, .exit = acpi_cpufreq_cpu_exit, .resume = acpi_cpufreq_resume, .name = "acpi-cpufreq", .owner = THIS_MODULE, .attr = acpi_cpufreq_attr, };
讲讲这个结构体中重要的几个元素的含义:
1、verify:是验证工作,目的验证当前的cpu的频率是否在限制范围内。用法如下: cpufreq_driver->verify(policy)
2、target:执行调频动作。
3、bios_limit:在bios中限制的cpu的频率范围。
4、init:初始化工作。
5、resume和suspend在power management中使用。
至此两个最重要的结构体完成了,其实我自己还是有些混乱的。呵呵。。。
继续回到执行调节频率的位置,在powersave governor中: __cpufreq_driver_target(policy, policy->min, CPUFREQ_RELATION_L),目的是使所有online状态的cpu处在最低频率运行。这里又涉及到一个有意思的参数relation。
relation只有两种值:CPUFREQ_RELATION_H和CPUFREQ_RELATION_L。
看看kernel的定义:
#define CPUFREQ_RELATION_L 0 /* lowest frequency at or above target ,查找大于等于其频率的最小频率*/
#define CPUFREQ_RELATION_H 1 /* highest frequency below or at target ,查找小于等于其频率的最大频率*/
这两个参数用的非常的频繁,主要用在cpufreq table中,用来查找合适的频率。当然对于powersave和performance governor是使用不到的。
cpufreq table是一个频率档,cpu的频率可以在这里面进行升降根据当前的cpu load。至于怎么分的,可以
cat /sys/devices/system/cpu/cpu0/cpufreq/scaling_available_frequencies,会显示当前电脑分了多少档。
cat /sys/devices/system/cpu/cpu0/cpufreq/stats/trans_table,这是一个统计表格,统计各个频率档使用的次数,
在调整过程中调到此频率的次数(个人理解)。
由于是powersave governor,所以当relation是CPUFREQ_RELATION_L的时候,查找>=policy->min的频率,最后找到的还是最小频率。
对于performance governor与powersave governor是类似的,仅仅做了两处改动:
1、
struct cpufreq_governor cpufreq_gov_performance = { .name = "performance", .governor = cpufreq_governor_performance, .owner = THIS_MODULE, };
name修改了。
2、 __cpufreq_driver_target(policy, policy->max,CPUFREQ_RELATION_H);这个调节频率的函数修改。思想是一样,只不过换成了调整为最高频率。
由于第一次发这种帖子,估计有很多不足。原来真的是要自己看懂的写出来和说出来是另外一回事,希望这篇文章不要误导了其他人,如果有,我先说声sorry。~_~.
相关文章推荐
- intell IDEA 代码自动提示功能没有LE ---File >Power Save Mode 被勾选了 去掉勾选就可以了
- interactive governor study for android
- WIFI power save 模式下的数据收发
- Performance study in Microsoft.ApplicationDataBlock.SqlHelper
- 无线power save
- SSD vs HDD price and performance study
- AndroidPowerSaveDebug总结
- Performance study in Microsoft.ApplicationDataBlock.SqlHelper
- android原生widget 电量控制(PowerSave)设计浅析
- power_save模式
- WIFI power save
- win7系统开机屏幕总是显示entering power save mode的解决方法
- Android Performance Case Study
- cpufreq 之powersave和performance governer的实现
- Android Studio代码自己主动提示无效(not available in Power Save mode)
- Android Studio代码自动提示无效(not available in Power Save mode)
- WIFI power save 模式下的数据收发
- Android Studio代码自动提示无效(not available in Power Save mode)
- Android Studio代码自动提示无效(not available in Power Save mode)
- userspace governor study