Linux动态频率调节系统CPUFreq之二:核心(core)架构与API

本文深入探讨Linux动态频率调节系统CPUFreq的核心代码架构,包括CPUFreq子系统的初始化、cpufreq_governor的注册、cpufreq_driver的注册、为每个CPU建立频率调整策略的过程,并介绍了核心层提供的其他API接口。
摘要由CSDN通过智能技术生成
转载

目录(?)[+]

上一节中,我们大致地讲解了一下CPUFreq在用户空间的sysfs接口和它的几个重要的数据结构,同时也提到,CPUFreq子系统把一些公共 的代码逻辑组织在一起,构成了CPUFreq的核心部分,这些公共逻辑向CPUFreq和其它内核模块提供了必要的API,像 cpufreq_governor、cpufreq_driver等模块通过这些API来完成一个完整的CPUFreq体系。这一节我们就来讨论一下核心 架构的代码架构以及如何使用这些公共的API接口。

/*****************************************************************************************************/

声明:本博内容均由http://blog.csdn.net/droidphone原创,转载请注明出处,谢谢!

/*****************************************************************************************************/

核心部分的代码都在:/drivers/cpufreq/cpufreq.c中,本系列文章我使用的内核版本是3.10.0.

1.  CPUFreq子系统的初始化


先看看具体的代码:

  1. static int __init cpufreq_core_init(void)  
  2. {  
  3.         int cpu;  
  4.   
  5.         if (cpufreq_disabled())  
  6.                 return -ENODEV;  
  7.   
  8.         for_each_possible_cpu(cpu) {  
  9.                 per_cpu(cpufreq_policy_cpu, cpu) = -1;  
  10.                 init_rwsem(&per_cpu(cpu_policy_rwsem, cpu));  
  11.         }  
  12.   
  13.         cpufreq_global_kobject = kobject_create_and_add("cpufreq", &cpu_subsys.dev_root->kobj);  
  14.         BUG_ON(!cpufreq_global_kobject);  
  15.         register_syscore_ops(&cpufreq_syscore_ops);  
  16.   
  17.         return 0;  
  18. }  
  19. core_initcall(cpufreq_core_init);  

可见,在系统的启动阶段,经由initcall机制,cpufreq_core_init被调用,由它来完成核心部分的初始化工作,其中:

cpufreq_policy_cpu    是一个per_cpu变量,在smp的系统下,每个cpu可以有 自己独立的调频policy,也可以所有的cpu都是用一种policy,这时候就有可能出现其中一个cpu管理着某个policy,而其它cpu因为也 使用同一个policy,这些cpu的policy的就交由那个管理cpu代管,这个per_cpu变量就是用来记录各个cpu的policy实际上是由 那个cpu进行管理的。初始化时都被初始化为-1了,代表现在还没有开始进行policy的管理。

接下来的kobject_create_and_add函数在/sys/devices/system/cpu这个节点下建立了一个cpufreq 节点,该节点的下面以后会用来放置当前governor的一些配置参数。参数cpu_subsys是内核的一个全局变量,是由更早期的初始化时初始化的, 代码在drivers/base/cpu.c中:

  1. struct bus_type cpu_subsys = {  
  2.         .name = "cpu",  
  3.         .dev_name = "cpu",  
  4. };  
  5. EXPORT_SYMBOL_GPL(cpu_subsys);  
  6.   
  7.   
  8. void __init cpu_dev_init(void)  
  9. {  
  10.         if (subsys_system_register(&cpu_subsys, cpu_root_attr_groups))  
  11.                 panic("Failed to register CPU subsystem");  
  12.   
  13.         cpu_dev_register_generic();  
  14. }  
这 将会建立一根cpu总线,总线下挂着系统中所有的cpu,cpu总线设备的根目录就位于:/sys/devices/system/cpu,同时, /sys/bus下也会出现一个cpu的总线节点。cpu总线设备的根目录下会依次出现cpu0,cpu1,...... cpux节点,每个cpu对应其中的一个设备节点。CPUFreq子系统利用这个cpu_subsys来获取系统中的cpu设备,并在这些cpu设备下面 建立相应的cpufreq对象,这个我们在后面再讨论。

这样看来,cpufreq子系统的初始化其实没有做什么重要的事情,只是初始化了几个per_cpu变量和建立了一个cpufreq文件节点。下图是初始化过程的序列图:


                                                                   图 1.1  核心层初始化

2.  注册cpufreq_governor


系统中可以同时存在多个governor策略,一个policy通过cpufreq_policy结构中的governor指针和某个 governor相关联。要想一个governor被policy使用,首先要把该governor注册到cpufreq的核心中,我们可以通过核心层提 供的API来完成注册:

[cpp] view plain
  • 0
    点赞
  • 1
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值