Linux cpuidle framework(1)_概述和软件架构

发布时间 - 2025-04-19 00:00:00    点击率:
  1. 前言

在计算机系统中,cpu的主要任务是执行程序,其核心步骤包括取指、译码和执行。然而,若无程序需要执行,cpu如何处理这一情况呢?有人可能会认为直接停止运行即可,但实际上,决定何时停止以及如何停止需要在复杂的软硬件环境中仔细考虑。

让我们转向Linux内核,Linux系统中的CPU被两种程序所占用:一类是进程(或线程),即进程上下文;另一类是中断和异常的处理程序,即中断上下文。

进程负责处理事务,例如读取用户输入并在屏幕上显示。当事务处理完毕,如用户不再输入且无新内容需显示时,进程可以释放CPU,但随时准备重新占用(如用户突然按键)。同样,若系统无中断或异常事件,CPU不会在中断上下文中花费时间。

在Linux内核中,CPU这种无所事事的状态被称为idle状态,而cpuidle框架正是管理这种状态的工具。

注:cpuidle框架系列文章将以ARM64为例平台。由于ARM64发布时间较短,早期版本的内核中没有相关代码,因此我们选择了最新的3.18-rc4版本的内核。

  1. 功能概述

曾经,Linux内核的cpu idle框架非常简单,简单到driver工程师只需在“include\asm-arm\arch-xxx\system.h”中定义一个名为arch_idle的内联函数,并在该函数中调用内核提供的cpu_do_idle接口即可,其余的实现内核会帮我们完成,如下:

static inline void arch_idle(void)
{
    cpu_do_idle();
}

尽管简单,但这包含了idle处理的两个关键点:

1)idle进程

idle进程的存在是为了解决“何时idle”的问题。

我们知道,Linux系统运行的基础是进程调度。当所有进程都不再运行时,即为CPU idle状态。内核通过一个简单的方法来判断这种状态:在init进程(系统的第一个进程)完成初始化任务后,将其转变为idle进程。由于idle进程的优先级最低,当其被调度时,说明系统中其他进程已停止运行,即CPU已idle。最终,idle进程会调用idle指令(如WFI),使CPU进入idle状态。

“ARM WFI和WFE指令”中提到,WFI Wakeup events会将CPU从WFI状态唤醒,这些事件通常是一些中断事件。因此,CPU唤醒后会执行中断处理程序,处理程序中会唤醒某些进程。当处理程序返回时,进行调度,如果没有其他进程需要执行,调度器会恢复idle进程的运行,当然,idle进程不会做任何事情,继续进入idle状态,等待下一次唤醒。

2)WFI

WFI用于解决“如何idle”的问题。

通常情况下,ARM CPU在idle时可以使用WFI指令,将CPU置于等待中断状态。在这种状态下,至少会关闭ARM核的时钟,以节省功耗(具体实现取决于ARM核的设计,可参考“ARM WFI和WFE指令”)。

也许您会觉得,上述过程已经足够好,为什么还要开发cpuidle框架?我的理解是:

  1. 软件架构

在Linux内核中,cpuidle框架位于“drivers/cpuidle”文件夹中,包含cpuidle核心、cpuidle调控器和cpuidle驱动三个模块,再结合位于内核调度中的cpuidle入口,共同完成CPU的idle管理。软件架构如下图:

1)内核调度模块

位于kernel\sched\idle.c中,负责实现idle线程的通用入口(cpuidle入口)逻辑,包括idle模式的选择和idle的进入等。

2)cpuidle核心

cpuidle核心负责实现cpuidle框架的整体结构,主要功能包括:

cpuidle核心的代码主要包括:cpuidle.c、driver.c、governor.c、sysfs.c。

3)cpuidle驱动

不同的架构和CPU核会有不同的cpuidle驱动,平台驱动开发者可以在cpuidle核心提供的框架下开发自己的cpuidle驱动。代码主要包括:cpuidle-xxx.c。

4)cpuidle调控器

Linux内核的框架有两种比较固定的抽象模式:

模式2的解释可能有些抽象,但在cpuidle的场景中容易理解:

前面提到,许多CPU提供了多种idle级别(即所谓的“方案”),这些idle级别的主要区别在于“idle时的功耗”和“退出时的延迟”。cpuidle驱动(机制)负责定义这些idle状态(每个状态的功耗和延迟分别是多少),并实现进入和退出的相关操作。最终,cpuidle驱动会将这些信息传递给调控器,由调控器根据具体的应用场景决定选择哪种idle状态(策略)。

内核中的cpuidle调控器都位于governors/目录下。

  1. 软件流程

在阅读本章之前,请先阅读以下三篇文章:

Linux cpuidle framework(2)_cpuidle核心

Linux cpuidle framework(3)_ARM64通用CPU idle驱动

Linux cpuidle framework(4)_menu调控器

前面提到过,内核会在系统启动完成后,在init进程(或线程)中处理cpuidle相关事务。大致过程如下(内核启动相关的分析将在其他文章中详细介绍):

cpu_startup_entry流程:

具体代码比较简单,不再分析,但有一点需要特别说明:

使用cpuidle框架进入idle状态时,本地irq处于关闭状态,因此从idle返回时,只能继续执行,直到irq被打开,才能执行相应的中断处理程序,这与传统的cpuidle不同。同时,这也间接验证了“Linux cpuidle framework(4)_menu调控器”中提到的,为什么menu调控器在reflect接口中只是简单地设置一个标志。因为reflect是在关闭中断时被调用的,需要尽快返回,以便处理中断事件。


# linux  # 工具  # 区别  # 为什么  # 架构  # include  # 接口  # 线程  # 事件  # 并在  # 会将  # 主要包括  # 自己的  # 发布时间  # 这一  # 是在  # 会有  # 第一个  # 让我们 


相关栏目: 【 网站优化151355 】 【 网络推广146373 】 【 网络技术251813 】 【 AI营销90571


相关推荐: 怎么制作网站设计模板图片,有电商商品详情页面的免费模板素材网站推荐吗?  如何用AI一键生成爆款短视频文案?小红书AI文案写作指令【教程】  Laravel如何使用Socialite实现第三方登录?(微信/GitHub示例)  Laravel如何使用Spatie Media Library_Laravel图片上传管理与缩略图生成【步骤】  Laravel怎么进行数据库回滚_Laravel Migration数据库版本控制与回滚操作  微信公众帐号开发教程之图文消息全攻略  Laravel怎么生成URL_Laravel路由命名与URL生成函数详解  Swift中swift中的switch 语句  Laravel如何安装Breeze扩展包_Laravel用户注册登录功能快速实现【流程】  Win11怎么关闭透明效果_Windows11辅助功能视觉效果设置  如何在云指建站中生成FTP站点?  Laravel如何配置任务调度?(Cron Job示例)  Laravel数据库迁移怎么用_Laravel Migration管理数据库结构的正确姿势  公司网站制作价格怎么算,公司办个官网需要多少钱?  非常酷的网站设计制作软件,酷培ai教育官方网站?  JS经典正则表达式笔试题汇总  免费制作统计图的网站有哪些,如何看待现如今年轻人买房难的情况?  手机钓鱼网站怎么制作视频,怎样拦截钓鱼网站。怎么办?  UC浏览器如何设置启动页 UC浏览器启动页设置方法  如何快速查询域名建站关键信息?  Laravel任务队列怎么用_Laravel Queues异步处理任务提升应用性能  Laravel如何处理和验证JSON类型的数据库字段  详解vue.js组件化开发实践  胶州企业网站制作公司,青岛石头网络科技有限公司怎么样?  高防服务器如何保障网站安全无虞?  JavaScript如何实现路由_前端路由原理是什么  如何在建站主机中优化服务器配置?  软银砸40亿美元收购DigitalBridge 强化AI资料中心布局  Laravel怎么实现API接口鉴权_Laravel Sanctum令牌生成与请求验证【教程】  网站建设要注意的标准 促进网站用户好感度!  b2c电商网站制作流程,b2c水平综合的电商平台?  标题:Vue + Vuex 项目中正确使用 JWT 进行身份认证的实践指南  韩国网站服务器搭建指南:VPS选购、域名解析与DNS配置推荐  百度输入法ai组件怎么删除 百度输入法ai组件移除工具  如何在景安云服务器上绑定域名并配置虚拟主机?  php485函数参数是什么意思_php485各参数详细说明【介绍】  Laravel如何连接多个数据库_Laravel多数据库连接配置与切换教程  Laravel如何实现邮箱地址验证功能_Laravel邮件验证流程与配置  Laravel如何实现API版本控制_Laravel API版本化路由设计策略  微博html5版本怎么弄发语音微博_语音录制入口及时长限制操作【教程】  Google浏览器为什么这么卡 Google浏览器提速优化设置步骤【方法】  java ZXing生成二维码及条码实例分享  Laravel Pest测试框架怎么用_从PHPUnit转向Pest的Laravel测试教程  Windows驱动无法加载错误解决方法_驱动签名验证失败处理步骤  Android GridView 滑动条设置一直显示状态(推荐)  香港服务器建站指南:外贸独立站搭建与跨境电商配置流程  详解ASP.NET 生成二维码实例(采用ThoughtWorks.QRCode和QrCode.Net两种方式)  如何打造高效商业网站?建站目的决定转化率  微信小程序 五星评分(包括半颗星评分)实例代码  利用python获取某年中每个月的第一天和最后一天