You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

获取thermal_zone0引用返回错误指针,树莓派4B内核模块如何读取温度?

问题:树莓派4B内核模块读取thermal_zone0温度失败

我正在为运行64位树莓派OS的树莓派4B编写一个简单的Linux内核模块,目标是读取thermal_zone0的温度。通过cat /sys/class/thermal/thermal_zone0/temp可以正常获取温度,但用内核模块实现时遇到问题。

我的代码如下:

#include <linux/module.h>
#include <linux/kernel.h>
#include <linux/thermal.h>

static int __init my_module_init(void)
{
    struct thermal_zone_device *thermal_zone;
    thermal_zone = thermal_zone_get_zone_by_name("thermal_zone0");
    if (!thermal_zone) {
        pr_err("Failed to get thermal zone 0\n");
        return -ENODEV;
    }

    if(thermal_zone->ops->get_temp)  // <-- 加载时触发段错误
        pr_info("Get temp is defined");

    return 0;
}

static void __exit my_module_exit(void)
{
    pr_info("Module unloaded\n");
}

module_init(my_module_init);
module_exit(my_module_exit);

MODULE_AUTHOR("Your Name");
MODULE_DESCRIPTION("Example kernel module to interact with thermal_zone0");
MODULE_LICENSE("GPL");

目前的问题:

  • 加载模块时触发段错误,原因是thermal_zone为错误指针,解引用thermal_zone->ops出问题
  • 之前尝试读取温度时结果始终为0,确认由指针错误导致

已确认内核配置相关热模块已启用:

CONFIG_THERMAL = y
CONFIG_THERMAL_HWMON = y
# Broadcom热驱动
CONFIG_BCM2711_THERMAL=y

我的疑问:如何正确获取thermal_zone0的引用并读取其温度?


解决方案

1. 核心问题说明

thermal_zone_get_zone_by_name失败时返回错误指针而非NULL,直接用!thermal_zone判断会忽略错误;同时直接访问thermal_zone->ops不安全,应该使用内核封装的API操作。

2. 修正后的代码

#include <linux/module.h>
#include <linux/kernel.h>
#include <linux/thermal.h>
#include <linux/err.h>

static int __init my_module_init(void)
{
    struct thermal_zone_device *thermal_zone;
    int ret;
    unsigned long temp;

    // 获取thermal_zone0引用,该函数会增加设备引用计数
    thermal_zone = thermal_zone_get_zone_by_name("thermal_zone0");
    if (IS_ERR(thermal_zone)) {
        pr_err("Failed to get thermal zone 0, err: %ld\n", PTR_ERR(thermal_zone));
        return PTR_ERR(thermal_zone);
    }

    // 使用内核封装函数读取温度,避免直接访问ops
    ret = thermal_zone_get_temp(thermal_zone, &temp);
    if (ret) {
        pr_err("Failed to get temperature, err: %d\n", ret);
        goto put_thermal_zone;
    }

    // 转换为摄氏度输出(内核返回单位为毫摄氏度)
    pr_info("Current temperature: %lu.%03lu °C\n", temp / 1000, temp % 1000);

put_thermal_zone:
    // 释放thermal zone引用,防止内存泄漏
    thermal_zone_put(thermal_zone);
    return ret;
}

static void __exit my_module_exit(void)
{
    pr_info("Module unloaded\n");
}

module_init(my_module_init);
module_exit(my_module_exit);

MODULE_AUTHOR("Your Name");
MODULE_DESCRIPTION("Example kernel module to read thermal_zone0 temperature");
MODULE_LICENSE("GPL");

3. 关键修正点

  • 用IS_ERR宏判断返回值:正确识别错误指针类型的失败返回
  • 使用thermal_zone_get_temp读取温度:内核封装的安全函数,内部会检查ops->get_temp有效性
  • 添加thermal_zone_put:获取引用后必须释放,避免内核内存泄漏
  • 温度单位转换:将内核返回的毫摄氏度转换为常用的摄氏度格式

4. 编译与测试示例

Makefile参考:

obj-m += thermal_reader.o
KDIR := /lib/modules/$(shell uname -r)/build
PWD := $(shell pwd)

all:
    $(MAKE) -C $(KDIR) M=$(PWD) modules

clean:
    $(MAKE) -C $(KDIR) M=$(PWD) clean
  • 编译:执行make
  • 加载模块:sudo insmod thermal_reader.ko
  • 查看输出:dmesg | tail
  • 卸载模块:sudo rmmod thermal_reader

内容的提问来源于stack exchange,提问作者thapro

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.06.20 14:52:23