也正是因为Linux内核的唯一性,各个不同发布版本拥有相同的框架。Linux内核是在整个Linux系统的最底层,它负责管理硬件,运行用户程序,并保持系统整体的安全性和完整性。可以说是Linux系统的根和灵魂。图3-1中看到Linux内核还有另一层面的含义。这对于Linux内核同样适用。所以对Linux内核的剖析、学习和研究也不能独立于系统进行,而是要综合考虑应用、内核和硬件等各方面的信息和内容。这样才能更全面、深刻地理解Linux内核。......
2023-11-22
Linux内核的电源管理部分在X86架构上有ACPI(高级配置与电源管理接口),但是广大的嵌入式设备并不支持ACPI,而对嵌入式设备来说电源管理的需求更强烈,所以急需相关的功能实现。考虑到电源管理的需求涉及处理器和各种设备,一方面是处理器尽可能减少功耗,另一方面是设备尽可能减少功耗。减少功耗的功能框架各种各样,一种功能框架是不能满足电源管理的需求的。所以Linux内核将电源管理分成不同的功能模块来实现,这样通过各个功能模块整体工作来满足电源管理的需求。Linux内核电源管理功能如图5-30所示。
图5-30 Linux电源管理各个功能
从图5-30可见Linux内核的电源管理功能有与处理器相关的CPUIdle和CPUFreq,也有与设备相关的runtime pm,另外还有与整个系统待机时SLM(standby leakage management)相关的低功耗电源管理功能。但并不是只有这些功能,在时间管理中的dynamictick也属于降低功耗的功能。下面分别对这些功能框架进行介绍。
1ᤫCPUIdle
在初始化的时候有过介绍,系统在没有任务需要调度的时候会执行cpu_idle,使处理器处于休息状态,其中系统提供了pm_idle接口实现各种idle的省电功能。CPUIdle会将其改为自己的接口cpuidle_idle_call,这样在内核进入idle时就会调用相应的接口,从而进入合适的状态。接下来分析一下相关的功能:
分析代码可见,具体的驱动要提供多种状态,这些状态是和QoS相关的。所谓QoS就是指对于idle来说不是简单地睡就可以了,要考虑醒来工作是否可以正常,例如进入不同的状态系统睡眠和唤醒延时是不同的,而idle只是短时间进入低功耗,相关的任务更重要,不能为了进入功耗更低的状态而影响正常的工作,这就需要QoS机制。在标记状态的同时要标记唤醒的时间,由governor来根据当前的系统状态选择合适的低功耗状态进入,既要休息好又不能影响工作。CPUIdle睡眠示意如图5-31所示。
从图5-31可见,系统要考虑进入哪种状态与能够睡眠的时间、sleep和wakeup延时都是相关的,能睡眠的时间越长越应该进入更高级别的低功耗状态。menu governor是通过每个处理器的下一次tick的时间来决定可进入低功耗的时间,从而进行选择。
图5-31 CPUidle电源管理示意图
具体的设备驱动会在SoC电源管理部分进行讲解。
2ᤫCPUFreq
CPUFreq就是实现处理器的频率变化,其中会涉及DVFS来降低功耗,相关的硬件原理之前已经介绍。这里对Linux内核的软件实现进行分析。
在介绍无关性实现的时候,已经介绍了CPUFreq的框架(见图3-21),在CPUFreq中不管根据什么原则,是监视系统状态也好还是用户设置也好,在选择了相应的频率等级后最终都是通过__cpufreq_driver_target来进行频率设置的,其中会调用具体的设备target接口进入相应的频率等级。具体的驱动同样会在SoC电源管理部分进行讲解。
这里看看governor的实现,主要介绍ondemand governor。流程图如图5-32所示。
图5-32 ondemand流程图
从图5-32可见,ondemand governor主要是监控CPU的使用率是否超过一定的值,如果是就提高主频,如果使用率很低就降低主频,从而实现根据使用率的动态调节以达到按需使用的功能。相关的参数配置在/sys/devices/system/cpu/cpu0/cpufreq/目录下,可以根据需要进行设置。
3ᤫSLM
这两部分功能都和设备相关。首先来看看设备模型相关的初始化部分,如图5-33所示。
图5-33 设备模型电源管理相关初始化
从图5-33可见,其中涉及了设备Runtime pm的相关初始化,但是SLM的操作并不明显。其实设备的SLM相关操作已经隐含在device添加过程device_pm_add中,思考一下,SLM操作时要进入某种待机状态,其中会涉及所有的设备,自然将其放入系统的设备增加过程中。这样系统的SLM操作就可以通过设备模型统一管理了。下面来看看细节:
既然所有的设备都会通过device_add添加到设备模型中进行管理,那么相应的也会加入到设备功耗管理列表中进行管理。
那么系统如何进入待机状态呢?这就要看sys文件系统了,如图5-34所示。
图5-34 待机控制框图
从图5-34可见,/sys/power目录下的state文件用于设置具体的待机状态。通过enter_state即可进入相应的状态,最终要进入待机suspend状态才会调用dpm_suspend_noirq。下面来看看实现细节:
从代码中可见,是想让所有的设备都进入待机状态,下面来看看通过device_suspend_noirq实现,设备模型对具体的设备进入相应待机状态的操作:
从具体实现中可见,其操作逻辑是按照之前设备模型介绍,依据设备具体的情况进行的。对具体设备的电源管理实现,将在设备驱动中进行详细分析。SoC内部的接口设备通常都是platform_device,所以会执行bus的pm操作,具体如下:
而在suspend操作中会执行platform_pm_suspend_noirq,细节如下:
(www.chuimin.cn)
从中可见,具体的是调用相应的platform_driver接口函数,这样转换好处是使得platform_device只维护资源,而driver则是可以复用的操作接口。
再来看看使整个系统进入待机的接口:
以上分析主要是进入待机状态最后阶段的操作流程,而要使得设备和系统进入待机状态,只提供一个操作接口其实现的复杂度就太高了,另外由于设备层次以及设备操作的复杂性,在进入待机状态之前需要进行必要的保护,所以电源管理操作就应该提供不同阶段的操作接口,正如在dev_pm_ops中所见的各种函数接口。具体的suspend操作则分为suspend prepare、suspend、suspend noirq等几个不同的阶段,并在dev_pm_ops定义了相应的接口。为了遍历所有的设备并执行相应的操作,dpm(derice power management)也提供了相应的接口,分别是dpm_prepare、dpm_suspend和dpm_suspend_noirq。这样一来所有的设备就可以通过分阶段的操作完成必要的保护操作后进入待机状态,恢复过程操作则是待机操作的逆过程。
从分析可知,整个系统的待机操作是从外围设备开始,最后到和系统电源管理最紧密的系统设备,所以从电源管理的角度设备也是分层的,外围设备就是设备模型中的device,而系统设备是sysdev(如CPU、memory、核心时钟源、时间管理部分等都是通过sysdev_regis-ter注册的,这与最小系统所见设备抽象后的实体基本一致)。另外内核也为芯片提供了基本的suspend_ops待机操作接口来进行芯片级别的特殊操作。
4ᤫruntime pm和device wake
下面看看设备的runtime pm是如何实现的。每个设备的runtime pm初始化工作由pm_runtime_init来完成,具体分析如下:
从代码分析中可见,主要是进行相关属性的初始化,另外初始化了用于异步执行runt-ime pm操作的work(pm_init中会初始化workqueue pm_wq来异步执行设备的runtime pm操作)以及相应的进行多个上下文同步的等待队列。考虑设备驱动是可以在多个上下文以及执行实体中运行,而驱动操作的设备物理上是唯一的实体,这就要求对设备进行的动态电源操作时需要进行同步。
设备的runtime pm操作的状态同步都是通过dev_pm_info来完成的,其被包含在device中,这样在任何上下文对设备进行runtime pm操作的时候都可以同步。dev_pm_info的细节如下:
可见其中不仅包含设备runtime pm的本身状态信息,还包含不同操作方式(如同步、异步)的状态。设备的runtime pm操作最终是通过rpm_xxx来执行的,xxx代表不同的操作请求,主要是idle、suspend和resume。下面以rpm_suspend为例来分析具体的流程:
从分析中可见,runtime pm的操作很好地考虑了多上下文执行以及多种操作方式的情况,保证对于设备操作的同步。
除此之外系统提供了一系列的操作接口来帮助驱动进行runtime pm操作,下面是一些接口的例子:
具体设备的runtime pm的操作接口定义如下:
与SLM的操作接口类似都在dev_pm_ops中进行定义,会有设备及各种总线以及class进行实现,实际的操作也是要按照层次执行。
下面列举了一个设备驱动中如何使用runtime pm的简单例子。
probe阶段时流程通常如下:
需要进行工作时操作流程如下:
没有具体的工作时可以直接通过pm_runtime_suspend来使得设备进入suspend状态。具体的操作由驱动根据实际情况调用runtime pm提供的各种接口来完成。
设备在电源管理方面除了suspend和resume的功能外,还有就是能够唤醒系统的能力。在唤醒系统的能力方面device中的struct dev_pm_info有can_wakeup属性表示wakeup的能力和wakeup属性表示唤醒源的信息等,通过这些属性来标记设备wakup的能力以及状态。另外提供了和wakup相关的接口如下:
这里的接口主要满足对设备在一定时间内唤醒系统的相关需求,具体的wakeup源是定时器,驱动可以根据需要进行调用。另外在设备suspend的时候还可以通过device_may_wakeup来检查设备是否可能唤醒系统而进行必要的唤醒设置(主要通过对set_irq_wake的封装接口set_irq_wake来实现)。
至此对主要的电源管理功能都进行了介绍和分析。
有关深入剖析Linux内核与设备驱动的文章
也正是因为Linux内核的唯一性,各个不同发布版本拥有相同的框架。Linux内核是在整个Linux系统的最底层,它负责管理硬件,运行用户程序,并保持系统整体的安全性和完整性。可以说是Linux系统的根和灵魂。图3-1中看到Linux内核还有另一层面的含义。这对于Linux内核同样适用。所以对Linux内核的剖析、学习和研究也不能独立于系统进行,而是要综合考虑应用、内核和硬件等各方面的信息和内容。这样才能更全面、深刻地理解Linux内核。......
2023-11-22
VFS的实现是以“一切皆是文件”为需求出发点的。要理解VFS的框架首先看一下VFS和系统的静态关系框图,如图5-1所示。从图5-1可见,VFS是用户层的直接接口,是面向用户的服务。图5-1VFS和系统静态关系图在图5-2中每个节点被使用时都会在VFS层中创建dentry,这样可以快速通过文件名进行查找和定位,Linux内核中对dentry的管理组织形式如图5-3所示。以上是系统运行时VFS对文件名的组织管理,这是VFS管理的一个方面。......
2023-11-22
SPI总线框架对这两类设备进行管理,具体的框架如图7-6所示。通常的SPI驱动都是在内核实现并在内核态执行的,所以就不对spidev进行详细的分析。SPI总线框架整体的功能就是这样,接下来看看具体各部分的实现。在SPI总线框架中相应的实体是spi_board_info,内容如下:其中的主要信息是与总线信号相关的属性。......
2023-11-22
整体的frame buffer框架如图6-5所示。了解frame buffer的框架还要先从为用户提供的接口开始。图6-7可变参数中硬件信息的含义固定信息是在frame buffer的操作过程中并不发生变化的。从整体分析,frame buffer的框架很直接,主要就是直接管理实际的设备,而相关的操作与应用层直接相关。......
2023-11-22
DM 3730的I2C控制器框架如图7-4所示。图7-4引自《DM 3730芯片手册》中第2798页的框图。关于DM 3730I2C的驱动部分,主要分析相关初始化和总线传输的操作。由于I2C作为控制和获取状态信息,数据量并不大,而且相关的操作频率并不高,这样在中断中进行相关的处理,对系统的影响并不大。......
2023-11-22
从图3-2中可以理解Linux内核就是将硬件的功能抽象出来,为用户的应用程序提供各种系统服务。与用户相关的属性是与Linux内核中整体安全性相关的,这部分功能通常和硬件具体功能关系不大,而是附加在逻辑功能之上的属性。本书是以嵌入式系统为基础进行说明,所以将重点放在硬件设备的具体功能以及Linux内核在硬件之上的具体实现方面。Linux内核的整体框架如图3-3所示。图3-3清晰地展现了Linux内核的实现层次,以及应用层功能和硬件功能的对应关系。......
2023-11-22
1基本中断处理流程Linux内核的中断处理框架当然要满足之前提到的各种需求。对Linux内核来说,每个中断号都是通过irq_desc进行描述的,可以说irq_desc是中断处理的核心。通过这些抽象结构就可以实现整个中断处理的框架。2中断处理延时操作下面介绍系统如何解决中断中大数据量时的延时处理问题。图4-28是Linux内核中断处理流程。......
2023-11-22
相关推荐