linux 如何读取的cpu 温度? (真实平台)
author: hjjdebugdate: 2026年 05月 28日 星期四 11:36:20 CSTdescrip: linux 如何读取的cpu 温度? (真实平台)文章目录1. 读取温度.1.1 读取测试点参考温度1.2 读取测试点温差温度1.3 计算实际温度.2. 注册一个热区 :3. 测试4. 驱动源码 (82行)前面曾经写过一个虚拟平台读取cpu 温度, 只要完善读取温度函数,从真实机器上读取温度, 那就是真正的cpu温度.完整驱动代码见后面附录关键点梳理:1. 读取温度.通过读取某个特定寄存器来读取到温度.具体过程稍微复杂一点. 先读取一个参考值, 再读取到参考值的差值计算出温度.1.1 读取测试点参考温度#define MSR_IA32_TEMPERATURE_TARGET 0x1A2MSR : model specified register, 模型特定寄存器IA32_TEMPERATURE_TARGETIntel 统一命名地址固定 0x1A2作用: 该地址保存了 CPU 出厂烧录的温度阈值,或者说温度参考值, 或者说最大温度值. 一般是100或105所有测量的温度是以该值为参考的.特定的寄存器, 只能用特定的指令来读取.rdmsrl(MSR_IA32_TEMPERATURE_TARGET, msr_target);读取参考值到msr_target, 计算出最大温度tj_maxtj 就是test junction, 测试结点的意思1.2 读取测试点温差温度#define MSR_IA32_PACKAGE_THERM_STATUS 0x1B1rdmsrl(MSR_IA32_PACKAGE_THERM_STATUS, msr_status);读取cpu 温度温度到 msr_status.读取的数值并不直接代表温度值, 而是到参考值的差值.1.3 计算实际温度.所以温度是tj_max-tj_offset, 看看代码就一目了然.这个地址0x1b1 决定了读取的是哪里的温度值.2. 注册一个热区 :怎样执行到我们的驱动代码? 需要在内核上开一个窗口.这需要注册一个热区.intel_cpu_tz thermal_zone_device_register(“intel_cpu_real”, //类型名称,自定义0,0,NULL,intel_tz_ops, //操作函数intel_tz_params, //操作函数参数0,2000 //polling_delay,查询间隔);该函数会在内核上开一个窗口,使用户通过窗口访问到内部驱动.这个窗口就是/sysfs 文件. 具体为:/sys/devices/virtual/thermal/thernal_zoneX首先, 它是开在/devices/virtual 总线下, 因为它不具体对应设备,所以在virtual 线下就很合适.第2,它属于热区,故下级目录为thermal, 这两层目录是接口函数决定的.thermal_zoneX, 其中这个X 是代表的是zone编号. 由系统根据当前的zone个数来确定.函数中的参数意义也已经注明.如果我不这样开口子,而是注册一个cdev, 在/dev/创建一个字符设备, 也是可以的.不过内核为热区专门提供了函数接口thermal_zone_device_register 函数, 用它就更方便了.这样也了解到了其它thermal_zone 是怎么来的.3. 测试$ insmod intel_minimal_temp.ko$ lsmod$ dmesg[15031.287916] ✅ 本机CPU真实TJ Max临界温度 105 °C[15031.287995] ✅ 精准Intel CPU测温驱动加载完成[15031.287997] 读取温度命令: cat /sys/class/thermal/thermal_zoneX/tempinsmod 后,我们发现在/sys/class/thermal/下多出了thermal_zone4, 那就进入到该目录hjjhjj-laptop:/sys/devices/virtual/thermal/thermal_zone4$ cat temp51000还发现,我们新添的这个zone4 跟 zone3 的数值是一致的,这说明,我们的驱动是正确的, 而且它就等价于系统zone3.至此,消除了cpu温度测量的神秘性. 就是读一个MSR 来实现的. 而展现它,用thermal_zone来展示.我们也能写完整的驱动.附件代码给出了完整实现.4. 驱动源码 (82行)$ cat intel_minimal_temp.c#includelinux/module.h#includelinux/kernel.h#includelinux/init.h#includelinux/thermal.h#includeasm/msr.h// Intel 官方温度寄存器定义//#define MSR_IA32_PACKAGE_THERM_STATUS 0x1B1//#define MSR_IA32_TEMPERATURE_TARGET 0x1A2staticinttj_max100;// 全局存储本机真实临界温度staticintintel_real_get_temp(structthermal_zone_device*tz,int*temp){u64 msr_status;inttj_offset;// 读取CPU当前热状态rdmsrl(MSR_IA32_PACKAGE_THERM_STATUS,msr_status);// 提取距离过热临界点的剩余度数tj_offset(msr_status16)0xFF;// 用CPU原生真实TJ_MAX精准计算毫摄氏度*temp(tj_max-tj_offset)*1000;return0;}staticstructthermal_zone_device_opsintel_tz_ops{.get_tempintel_real_get_temp,//实现查看温度函数};staticstructthermal_zone_paramsintel_tz_params{.no_hwmontrue,};staticstructthermal_zone_device*intel_cpu_tz;staticint__initintel_temp_init(void){u64 msr_target;// 第一步自动读取CPU出厂自带的真实TJ Max临界温度rdmsrl(MSR_IA32_TEMPERATURE_TARGET,msr_target);tj_max(msr_target16)0xFF;pr_info(✅ 本机CPU真实TJ Max临界温度 %d °C\n,tj_max);// 严格适配 Linux 5.4 内核 完整8参数原型,注册一个热区intel_cpu_tzthermal_zone_device_register(intel_cpu_real,0,0,NULL,intel_tz_ops,intel_tz_params,0,2000//polling_delay);if(IS_ERR(intel_cpu_tz)){pr_err(❌ 温控域注册失败\n);returnPTR_ERR(intel_cpu_tz);}pr_info(✅ 精准Intel CPU测温驱动加载完成\n);pr_info( 读取温度命令: cat /sys/class/thermal/thermal_zoneX/temp\n);return0;}staticvoid__exitintel_temp_exit(void){thermal_zone_device_unregister(intel_cpu_tz);pr_info(✅ 驱动已安全卸载\n);}module_init(intel_temp_init);module_exit(intel_temp_exit);MODULE_LICENSE(GPL);MODULE_DESCRIPTION(自动TJ Max 100%对齐官方驱动版);