zoukankan      html  css  js  c++  java
  • Linux cpuidle framework【转】

    转自:https://www.cnblogs.com/LoyenWang/p/11379937.html

    背景

    • Read the fucking source code! --By 鲁迅
    • A picture is worth a thousand words. --By 高尔基

    说明:

    1. Kernel版本:4.14
    2. ARM64处理器
    3. 使用工具:Source Insight 3.5, Visio

    1. 介绍

    在Linux OS中,Idle进程的运行会让CPU进入cpuidle状态。当没有其他进程处于运行状态时,Scheduler会选择Idle进程来运行,此时CPU无所事事。

    在ARM64架构中,当CPU Idle时,会调用WFI指令(wait for interrupt),关掉CPU的Clock以便降低功耗,当有外设中断触发时,CPU又会恢复回来。

    cpuidle framework就是用来向上给Scheduler/Sysfs提供使用接口,向下用来对接不同架构的处理器,凡是框架基本都大同小异,屏蔽硬件层并抽象使用接口。

    相信你已经猜到了,cpuidle和电源管理相关。

    2. 框架

    代码路径:
    driver/cpuidle/cpuidle.c
    driver/cpuidle/driver.c
    driver/cpuidle/governor.c
    driver/cpuidle/sysfs.c
    kernel/shced/idle.c

    老规矩,上图:

    简单说明一下吧:调度器发现没有Task处在运行状态时,切换到Idle进程,此时通过cpuidle_idle_call接口调到cpuidle frameworkcpuidle framework会选择合适的策略来决定进入哪种状态,最终回调到底层的平台实现。

    SMP处理器都有cpuidle状态,而各个状态下的功耗都不同,是否进入cpuidle状态有两个重要的参考因素:

    • CPU进入-退出cpuidle状态的latency;
    • CPU处在cpuidle状态的功耗;

    Latency和功耗的tradeoff,是需要根据实际情况来选择策略的,也就是Governor的作用。

    3. 数据结构

    cpuidle core抽象出了三个数据结构:

    • cpuidle device:用于描述CPU核;
    • cpuidle driver: 针对CPU核的驱动;
    • cpuidle governor:主要根据cpuidle的device和driver状态来选择策略;

    图如下:

    3.1 cpuidle device

    针对每个CPU核都对应一个struct cpuidle_device结构,主要字段介绍如下:

    • registered:该cpu核是否注册进内核中;
    • enabled:该cpu核是否已经使能;
    • cpu:对应的cpu number;
    • last_residency:该cpu核上一次停留在cpuidle状态的时间(us);
    • state_count:cpuidle状态的个数;
    • states_usagestruct cpuidle_state_usage数组,记录每个cpuidle状态的统计信息,包括是否使能、进入该cpuidle状态的次数,停留在该cpuidle状态的总时间(us);
    • kobjs*:与sysfs组织相关,开发给用户层来操作底层;
    • device_list:全局链表,链接到cpuidle_detected_device上;

    3.2 cpuidle driver

    cpuidle driver用于驱动一个或多个CPU核,关键字段描述如下:

    • bctimer:用于驱动注册时判断是否需要设置broadcast timer;
    • states[]struct cpuidle_state数组,用于描述cpuidle的状态,需要按照功耗从大到小来排序,具体有多少个cpuidle状态,取决于device Tree中的定义,默认已经有state[0],如上图所示。
    • cpumask:用于表明支持哪些CPU核;

    struct cpuidle_state中的enter函数,是最终进入cpuidle状态的函数。不同处理器的cpuidle驱动实现,主要是填充state结构体。

    3.3 cpuidle governor

    governor结构主要提供不同的回调函数,最终由menu_governor填充,主要字段如下:

    • enable/disable:在设备驱动注册和注销的时候调用;
    • select:根据已有状态来选择一个cpuidle状态;
    • reflect:调用该接口告知governor,CPU上一次所处的cpuidle状态是哪个;

    流程

    cpuidle-arm.c为例,整个注册流程如下图:

    注册之后便将设备和驱动建立起连接关系了,最终cpuidle framework的用户便可通过接口来调用下层的接口,进而完成具体的硬件操作。

    Idle Task通过cpuidle_enter为入口,调用到cpuidle_framework,流程如下图:

    Idle Task调用cpuidle_enter之前,需要先通过governor来运用策略来选择将要进入的cpuidle state。入口为cpuidle_select,当完成状态切换后会调用cpuidle_reflect来将信息更新到governor。具体的图如下:

    其中Governor关于状态的策略选择,可以参考menu.c的注释,主要有三个决定因素:

    1. 功耗平衡点,也就是需要权衡考虑cpuidle状态带来的功耗节省和在该cpuidle状态下的停留时间,假如停留时间太短(小于target_residency),则不划算。
    2. 性能影响,那些具有大的延迟退出(exit_latency)的cpuidle state,通常会对工作负载产生较大影响,这个对系统管理员来说是不可接受的。此外,低性能往往也意味着低功耗。
    3. 延迟容忍度(从pmqos框架获取),在满足延迟容忍度latency_req的条件下,选择功耗最小的cpuidle状态。

    具体的策略不再分析,请直接看driver/cpuilde/menu.c代码及注释。

    作者:LoyenWang
    出处:https://www.cnblogs.com/LoyenWang/
    公众号:LoyenWang
    版权:本文版权归作者和博客园共有
    转载:欢迎转载,但未经作者同意,必须保留此段声明;必须在文章中给出原文连接;否则必究法律责任
  • 相关阅读:
    POJ 2251 Dungeon Master(bfs)
    POJ 3275 Catch That Cow(bfs)
    POJ 3984 迷宫问题(bfs+路径记录)
    POJ 3620 Avoid The Lakes
    ZOJ 2100 Seeding
    POJ 2245 Lotto
    HDU 1181 变形课
    dedecms网站栏目增加缩略图的方法-测试通过
    dedecms缩略图模糊终极完美解决办法
    dedecms 留言板中引用模板文件方法
  • 原文地址:https://www.cnblogs.com/sky-heaven/p/14155773.html
Copyright © 2011-2022 走看看