当前位置: 首页 > news >正文

linux thermal framework(4)_thermal governor

原文:蜗窝科技linux thermal framework(4)_thermal governor

1. 介绍

thermal governor是通过一定算法控制cooling device状态来控温的在这篇文章中,我们使用一个简单的step_wise governor来说明整个过程。

2. thermal governor相关的API以及功能分析

2.1 struct thermal_governor

/** * struct thermal_governor - structure that holds thermal governor information * @name:   name of the governor * @bind_to_tz: callback called when binding to a thermal zone.  If it *      returns 0, the governor is bound to the thermal zone, *      otherwise it fails. * @unbind_from_tz: callback called when a governor is unbound from a *          thermal zone. * @throttle:   callback called for every trip point even if temperature is *      below the trip point temperature * @governor_list:  node in thermal_governor_list (in thermal_core.c) */struct thermal_governor {    //1)name, 每个governor会有一个名字,在温控的governors中,常见的有power_allocator/userspace/step_wise    char name[THERMAL_NAME_LENGTH];    //2)bind_to_tz, governor绑定thermal_zone的回调函数    int (*bind_to_tz)(struct thermal_zone_device *tz);    //3)unbind_from_tz,governor和thermal_zone解绑的回调函数    void (*unbind_from_tz)(struct thermal_zone_device *tz);    int (*throttle)(struct thermal_zone_device *tz, int trip);    //4)governor_list,thermal core通过一个链表来管理所有的governors,这个是该governor在链表中的节点    struct list_head    governor_list;    ANDROID_KABI_RESERVE(1);};

2.2 thermal_governor的注册

linux在lds中静态定义了一个governor_thermal_table,每个thermal governor会在这个table中添加一个entry,以step_wise为例:

kernel-6.6/drivers/thermal/gov_step_wise.c

/*  * 如果内核配置启用了 THERMAL(温度控制模块),则定义 THERMAL_TABLE 宏, * 否则定义为空(避免未启用时产生无效代码) */#ifdef CONFIG_THERMAL    /*      * THERMAL_TABLE 宏定义:     * 用于在内存中按 8 字节对齐方式放置温度控制相关的数据表,     * 并通过 BOUNDED_SECTION_POST_LABEL 标记其起始和结束地址     */    #define THERMAL_TABLE(name)                     \        . = ALIGN(8);                           /* 按 8 字节对齐当前地址 */ \        BOUNDED_SECTION_POST_LABEL(__##name##_thermal_table,  /* 定义符号表起始 */ \                           __##name##_thermal_table,, _end)   /* _end 表示结束位置 */#else    /* 如果未启用 THERMAL,则 THERMAL_TABLE 宏不执行任何操作 */    #define THERMAL_TABLE(name)#endif/*  * 定义 step_wise 温控策略的结构体: * 该策略通过逐步调整冷却设备(如风扇/CPU调频)来控制温度 */static struct thermal_governor thermal_gov_step_wise = {    .name   = "step_wise",      /* 策略名称(用于匹配和调试) */    .manage = step_wise_manage, /* 核心管理函数指针,实现温度调节逻辑 */};/*  * 向内核注册此温控策略: * THERMAL_GOVERNOR_DECLARE 宏会将结构体放入特定内存段(如 __thermal_governor), * 供内核初始化时调用 */THERMAL_GOVERNOR_DECLARE(thermal_gov_step_wise);

thermal core在初始化的过程中,会遍历governor_thermal_table中所有的entry,即所有的governor,将其加进governor_list中,比较这个governor和DEFAULT_THERMAL_GOVERNOR名字是否想同,相同的话,就将系统默认的governor设置为这个governor,遍历所有的thermal_zone,如果这个governor的名字和thermal zone本身有的governor名字相同,则会设置thermal zone的governor

对governor来说,主要的回调函数就是manage,manage会在thermal zone拥有的monitor每次check thermal zone的温度的时候调用该thermal zone对应的governor->manage函数,我们可以看下step_wise的manage函数是怎么调温的

2.3 step_wise温控算法

首先我们还是用这张图结合stepwise的算法来描述以下过程:

0

/** * step_wise_manage - 温控策略核心管理函数(逐步调节) * @tz: 指向 thermal_zone_device 的指针,代表一个温度监控区域 * * 功能:根据温度变化趋势逐步调整冷却设备状态(如风扇转速/CPU频率)。 *      若温度上升,则逐级增强冷却;若温度下降,则逐级恢复性能。 */static void step_wise_manage(struct thermal_zone_device *tz){    const struct thermal_trip_desc *td;  // 温度触发点描述符    struct thermal_instance *instance;   // 冷却设备实例    /* 锁断言:确保调用时已持有温度区域的锁 */    lockdep_assert_held(&tz->lock);    /*     * 核心调节逻辑:     * 1. 遍历所有温度触发点(trip point),跳过无效/危险温度点     * 2. 对每个有效触发点,更新其关联冷却设备的阈值状态     * 3. 最终统一更新所有冷却设备状态     */    for_each_trip_desc(tz, td) {        const struct thermal_trip *trip = &td->trip;        /* 跳过以下触发点:         * - 未配置有效温度值(THERMAL_TEMP_INVALID)         * - 关键温度(CRITICAL,可能触发紧急关机)         * - 过热温度(HOT,可能触发强制降频)         */        if (trip->temperature == THERMAL_TEMP_INVALID ||            trip->type == THERMAL_TRIP_CRITICAL ||            trip->type == THERMAL_TRIP_HOT)            continue;        /* 更新当前触发点的温度状态(根据趋势调整阈值) */        thermal_zone_trip_update(tz, td, td->threshold);    }    /* 遍历所有触发点及其关联的冷却设备实例 */    for_each_trip_desc(tz, td) {        list_for_each_entry(instance, &td->thermal_instances, trip_node)            /* 通知冷却设备更新状态(如调整风扇档位) */            thermal_cdev_update(instance->cdev);    }}

1)首先遍历这个thermal zone所有的trip:for_each_trip_desc,过滤掉其中无效或者档位过高的trip,然后调用thermal_zone_trip_update这个函数来更新trip信息,为选择最佳cooling device state做准备

2)在做好更新后,重新遍历trip,thermal_c

继续看下thermal_zone_trip_update是如何更新trip信息的:

kernel-6.6/drivers/thermal/gov_step_wise.c

/** * thermal_zone_trip_update - 更新温控触发点状态并调整冷却设备 * @tz: 指向thermal_zone_device的指针,代表一个温度监控区域 * @trip_id: 要处理的温度触发点ID * * 功能:根据温度趋势和当前温度与触发点的关系,动态调整冷却设备状态 *       支持被动冷却(如CPU降频)和主动冷却(如风扇调速)两种模式 */static void thermal_zone_trip_update(struct thermal_zone_device *tz, int trip_id){    // 获取指定触发点的配置信息    const struct thermal_trip *trip = &tz->trips[trip_id];    enum thermal_trend trend;       // 温度变化趋势(上升/下降/稳定)    struct thermal_instance *instance; // 冷却设备实例    bool throttle = false;           // 是否需要抑制性能的标志    int old_target;                  // 保存设备之前的控制状态    // 获取温度变化趋势(通过历史温度数据分析)    trend = get_tz_trend(tz, trip_id);    /* 基础节流判断:当前温度超过触发温度时激活节流 */    if (tz->temperature >= trip->temperature) {        throttle = true;        // 记录跟踪点(用于ftrace等性能分析工具)        trace_thermal_zone_trip(tz, trip_id, trip->type);    }    /* 调试日志:打印触发点关键参数 */    dev_dbg(&tz->device, "Trip%d[type=%d,temp=%d]:trend=%d,throttle=%d\n",        trip_id, trip->type, trip->temperature, trend, throttle);    /* 遍历该温控区域下的所有冷却设备实例 */    list_for_each_entry(instance, &tz->thermal_instances, tz_node) {        // 跳过不属于当前触发点的实例        if (instance->trip != trip)            continue;        // 保存当前状态用于后续比较        old_target = instance->target;        // 计算新目标状态(考虑温度趋势和节流需求)        instance->target = get_target_state(instance, trend, throttle);        /* 调试日志:显示状态变化 */        dev_dbg(&instance->cdev->device, "old_target=%d, target=%d\n",                old_target, (int)instance->target);        /* 跳过无变化且已初始化的实例(优化性能) */        if (instance->initialized && old_target == instance->target)            continue;        /*          * 被动冷却处理(如CPU调频):         * 当设备从未激活状态变为激活时,增加被动冷却计数         */        if (old_target == THERMAL_NO_TARGET &&            instance->target != THERMAL_NO_TARGET)            update_passive_instance(tz, trip->type, 1); // 增加计数        /*          * 当设备从激活状态变为未激活时,减少被动冷却计数          */        else if (old_target != THERMAL_NO_TARGET &&               instance->target == THERMAL_NO_TARGET)            update_passive_instance(tz, trip->type, -1); // 减少计数        // 标记实例已完成初始化        instance->initialized = true;        /* 标记冷却设备需要更新状态 */        mutex_lock(&instance->cdev->lock);        instance->cdev->updated = false; // 触发后续thermal_cdev_update()        mutex_unlock(&instance->cdev->lock);    }}

1)trend = get_tz_trend,首先得到温度趋势,上升:THERMAL_TREND_RAISING or 下降:THERMAL_TREND_DROPPING

2)throttle:是否达到trip限制的温度

3)遍历这个trip所有的thermal instances,调用get_target_state获得目标状态,如果目标状态和原有状态不同,就设置cooling device的update参数为false,在后面的函数中更新为target state

get_target_state是获取目标状态的主函数:

/** * get_target_state - 根据温度趋势和节流需求计算冷却设备的目标状态 * @instance: 温控实例(关联特定触发点和冷却设备) * @trend: 当前温度变化趋势(上升/下降/稳定) * @throttle: 是否需要抑制性能(温度超过触发点时设为true) * * 返回值: 冷却设备的目标状态值(或THERMAL_NO_TARGET表示不激活) * * 核心逻辑: * 1. 温度高于触发点时: *    a. 趋势上升 → 提高冷却强度 *    b. 趋势下降 → 保持当前状态(避免频繁调整) * 2. 温度低于触发点时: *    a. 趋势上升 → 保持当前状态 *    b. 趋势下降 → 降低冷却强度(若已达下限则关闭冷却) */static unsigned long get_target_state(struct thermal_instance *instance,                enum thermal_trend trend, bool throttle){    struct thermal_cooling_device *cdev = instance->cdev;    unsigned long cur_state;      // 当前冷却状态    unsigned long next_target;    // 待计算的目标状态    /* 获取冷却设备当前状态(如风扇转速档位) */    cdev->ops->get_cur_state(cdev, &cur_state);    next_target = instance->target; // 默认保持原状态    dev_dbg(&cdev->device, "cur_state=%ld\n", cur_state);    /* 处理未初始化的实例 */    if (!instance->initialized) {        if (throttle) {            // 温度超标时:当前档位+1,并限制在有效范围内[lower,upper]            next_target = clamp((cur_state + 1), instance->lower, instance->upper);        } else {            // 温度安全时:标记为不激活            next_target = THERMAL_NO_TARGET;        }        return next_target;    }    /* 温度超过触发点时的处理 */    if (throttle) {        // 仅当温度持续上升时才提高冷却强度(避免震荡)        if (trend == THERMAL_TREND_RAISING) {            next_target = clamp((cur_state + 1), instance->lower, instance->upper);        }    }     /* 温度低于触发点时的处理 */    else {        // 仅当温度持续下降时才降低冷却强度        if (trend == THERMAL_TREND_DROPPING) {            if (cur_state <= instance->lower) {                // 已达最低档位则关闭冷却                next_target = THERMAL_NO_TARGET;            } else {                // 否则降低一档                next_target = clamp((cur_state - 1), instance->lower, instance->upper);            }        }    }    return next_target;}

0

target state的逻辑总结:如果当前温度高于trip温度,如果趋势是上升,选择更高的cooling 状态,如果趋势是下降,do nothing; 如果当前温度低于trip温度,如果趋势是上升,do nothing,如果趋势是下降,用更低的cooling状态,如果已经是最低的状态了,那么就deactive这个thermal instance

相关文章:

  • Linux 忘记root密码如何解决-linux025
  • 2.1 Windows VS2019编译FFmpeg 4.4.1
  • PCL 生成圆柱面点云
  • 人工智能-准确率(Precision)、召回率(Recall) 和 F1 分数
  • YOLO优化之双池化下采样融合块、注意力引导逆残差块
  • 第20篇:数据库中间件的热点 Key 缓存一致性策略与分布式协调机制
  • Spring Boot 整合 Swagger 快速生成 API 文档的最佳实践
  • Axure应用交互设计:中继器数据向多种类型元件赋值
  • jxWebUI--简单易用的webUI库
  • Iceberg与Hive集成深度
  • linux多线程之条件变量
  • 学习昇腾开发的第三天--将服务器连接网络
  • Android 与 ESP-01 WIFI模块通信
  • HTTP协议简易入门
  • Vue3相关知识3
  • JS当中怎么定义一个类
  • Linux信号机制:进程异步通信的秘密
  • Kafka 可靠性保障:消息确认与事务机制(一)
  • XR-RokidAR-UXR3.0-Draggable 脚本解析
  • HTML的最基础入门知识,从零开始逐步讲解,适合为后续爬虫技术打基础:
  • 三明企业网站建设/免费网站推广网站破解版
  • 网站免费正能量直接进入检察官/挖掘关键词的工具
  • 市场调研报告范文/合肥seo网络优化公司
  • 有没有专门做线下活动的网站/sem是什么意思
  • 哪家公司网站制作好/深圳推广公司哪家好
  • 徐州人才网官网登录/牡丹江seo