最近在搞一个读取CPU温度的驱动,网上翻了好多资料,可发现全是copy的,原稿也就两三篇,可经实践发现其中不乏错误与片面,让人着实走弯路,燃起了我要总结一番的欲望。

这个驱动搞了一个多星期,总算可以运行了,测试了几台Intel和AMD的机器也都测试通过,测试对比用的是CPUID HWMonitor和Core Temp。

Intel和AMD的CPU中都有温度传感器(DTS),每个核心都有一个,温度就是由此获取来的,多核cpu可以使用 SetProcessAffinityMask API 来指定执行的CPU。

首先是利用CPUID来区分是Intel型号还是AMD型号,利用汇编和函数都可实现,考虑到64位系统不支持嵌入汇编,所以还是直接利用API函数就行。

CPUID其实就是对eax执行cpuid指令,返回信息储存在eax,ebx,ecx,edx中,令eax=0,可将CPU厂商信息返回在ebx,ecx,edx中,

int CPUInfo[4];

__cpuid(CPUInfo,0);

Intel信息字符串为GenuineIntel,AMD为AuthenticAMD,只判断前4个字符就可以,只需与CPUInfo[1](ebx)比较就可得出型号。

接下来说如何获取温度,先从简单的说起,Intel实现起来比较简单:

先以eax=0 执行 cpuid 检测 eax 支持的最大命令数,如果小于6就肯定不支持DTS。然后以eax=6 执行 cpuid,  然后测试 eax 第一位是否为1,如果为1表示CPU支持DTS。

读取DTS:以 ecx=0x1A2 执行 rdmsr 指令, 测试 eax 的第30位是否为 1, 如果为 1 表示温度计算的初始值为 85 度否则表示从100度开始计算,这个值称为 Tjunction.

eax=__readmsr(0x01A2)

然后以 ecx=0x19c 执行 rdmsr 指令,  eax 的 16-23 位为表示当前DTS 值,当前温度要以下面公式计算.

当前cpu温度 = Tjunction - DTS

注意  signature 为 0x6f1, 0x6f0的 CPU DTS 值直接代表当前温度而不用Tjunction 相减. 而 signature 小于等于 0x6f4 的 Tjunction 一直为100。

AMD就比较恶心了,研究了挺长时间:

AMD温度存储在NB寄存器中,这是一个热传感寄存器。AMD的CPU分为K8和K10,K8的温度存储在这个寄存器的23-14位,K10的在31-21位。

要访问这个状态寄存器,需要对PCI进行读写。

先介绍俩个PCI用到的寄存器,CF8h和CFCh

CF8h: 存放配置空间的地址(CONFIG-ADDRESS)

CFCh: 保存配置空间的读写数据(CONFIG-DATA)

这两个空间对应于PCI桥路的两个寄存器,当桥路看到CPU在局部总线对这两个 I/O空间进行双字操作时,就将该I/O操作转变为PCI总线的配置操作。

温度读取

如果是K8的话,可以忽略低俩位,读取23-16就可以了,当然也可以读23-14,然后\4或者>>2;

如果是K10的话,那就读取31-21

如何判断K8,K10

__cpuid(CPUInfo,1); //cpuid执行1,取出eax

t=CPUInfo[0];

family=((t>>20)&0xFF) + ((t>>8)&0xF);

model=((t>>12)&0xF0) + ((t>>4)&0xF);

stepping=t&0xF;

如果Family ==0xf 而除了

(((model == 4) && (stepping == 0)) ||

((model == 5) && (stepping <= 1)))

则为K8

如果Family > 0xf,一般是G。那就是K10

温度的计算公式

K8 Temp = Value - 49'.   49这个值需要修正的:if (model >= 0x69 && model != 0xc1 && model != 0x6c && model != 0x7c)  temp=Value-49+21;

K10 Temp = Value / 8'.

IO访问PCI总线设备配置空间配置空间地址寄存器的格式:

31      24 23         16 15            11 10              8 7               2 1   0

| reserve | bus number | device number | function number | register number | 0 | 1/0 |

所以知道 bus number, device number, function number, register number后,可以这么来构造配置空间地址寄存器

IOADDR = 0x80000000+bus*0x10000 +(device*8)*0x100 + uFunction&0x07 + register number&~3;

为什么需要0x80000000呢,因为

当CPU发出对I/O空间CFCh的操作时,PCI桥路将检查配置空间地址寄存器CF8h的31位。如果为1,就在PCI总线上产生一个相应的配置空

间读或写操作,0x80000000就是使配置空间地址寄存器为1。

经过上面的讨论后,可以写成

#define DeviceSlot(uDevice, uFunction) ((((uDevice)&0x1f)<<3)|((uFunction)&0x07))

#define GetDevice(uBus,uSlot,uAddress) (0x80000000L |((uBus&0xff)<<16)|(uSlot<<8)|(uAddress&~3));

这样知道 uBus, uDevice, uFunction, uAddress后就可以通过IO指令来读写了。

对于K8, uAddress为0xE4,对于K10 uAddress为0xA4

怎样获取uBus, uDevice, uFunction从上面知道GetDevice需要 uBus, uDevice, uFunction的。

可以扫描PCI总线来获取,对于AMD K8来说,设备ID为0x1103,对于K10来说,设备ID为0x1203。 二者的uFunction都为3.

通过扫描PCI总线,匹配设备ID来获取。

BOOL get_bus_dev( int devieid,int *BUS, int *DEV ) //遍历PCI得到bus和dev

{

ULONG bus;

ULONG dev;

ULONG func=3; //K8 K10 fun为3

unsigned long Size;

PCI_COMMON_CONFIG PciConfig;

PCI_SLOT_NUMBER SlotNumber;

for(bus = 0; bus <= 255; ++bus)

{

for(dev = 0; dev <= 31; ++dev)

{

SlotNumber.u.AsULONG = 0;

SlotNumber.u.bits.DeviceNumber = dev;

SlotNumber.u.bits.FunctionNumber = func;

RtlZeroMemory(&PciConfig, sizeof(PCI_COMMON_CONFIG));

Size = HalGetBusData(PCIConfiguration,

bus,

SlotNumber.u.AsULONG,

&PciConfig,

PCI_COMMON_HDR_LENGTH); //API函数

if (Size==PCI_COMMON_HDR_LENGTH)

{

if ( devieid==PciConfig.DeviceID )

{

*BUS=bus;

*DEV=dev;

DbgPrint("BUS:%d \n",bus);

DbgPrint("DEV:%d \n",dev);

return TRUE;

}

}

}

}

return FALSE;

}

然后进行IO读写就可以获取温度了,K8:

static once =1;

if (once)

{

int bus,dev,slot;

if ( !get_bus_dev(0x1103,&bus,&dev) )

{

DbgPrint("获取BUS、DEV失败! \n");

return;

}

slot=DeviceSlot(dev,0x3);  //上面定义的宏

IO_ADDRE=GetDevice(bus,slot,0xE4);  //上面定义的宏

once=0;

}

_outpd(0xCF8,IO_ADDRE);//端口读写

CPUTemp=_inpd(0xCFC);//端口读写

CPUTemp=(CPUTemp>>16)&0xFF;

CPUTemp=CPUTemp - g_Offset;//g_Offset为49-21

DbgPrint("CPUTemp: %d \n",CPUTemp);

读取cpu温度的api_读取CPU核心温度相关推荐

  1. 计算机中央处理器降温,CPU温度过高怎么办 CPU温度过高降温方法【详解】

    CPU温度过高怎么办? CPU也就是我们常说的中央处理器,它是一块超大规模的集成电路,是一台计算机的运算核心和控制核心.如果cpu温度过高会严重损害电脑. 下面,我们就来看看如何给电脑降降温. 1.首 ...

  2. 解答:CPU温度多少正常?CPU温度过高怎么解决?

    CPU作为电脑工作的核心部件同时也是发热大户,然而CPU的温度多少是正常的呢?温度过高怎么解决?包括MTOOU.INFO穆童自己的内的很多人在感觉电脑温度不正常时总会有这样的疑问,下面结合我个人的经验 ...

  3. python查看cpu温度_Python如何读取CPU和GPU的温度?

    该楼层疑似违规已被系统折叠 隐藏此楼查看此楼 到第三步报的错 @MaterialFan Traceback (most recent call last): File "", li ...

  4. python获取cpu温度_Python如何读取CPU和GPU的温度?

    该楼层疑似违规已被系统折叠 隐藏此楼查看此楼 到第三步报的错 @MaterialFan Traceback (most recent call last): File "", li ...

  5. python获取cpu温度 window_Python如何读取CPU和GPU的温度?

    该楼层疑似违规已被系统折叠 隐藏此楼查看此楼 到第三步报的错 @MaterialFan Traceback (most recent call last): File "", li ...

  6. suse linux查看CPU温度,Ubuntu下查看CPU温度风扇转速和硬盘温度

    夏天到了,这几天本本的温度也飙升起来,在WinXP下玩了会CS,结果CPU一下就到了80度,吓得我赶紧关了. 下午Win7 64位旗舰版也下载完了,准备体验一下,就装个系统,网页都不浏览的情况下CPU ...

  7. linux上监控cpu温度,Linux怎样监控CPU温度?

    安装测试系统: 硬件:普通PC机, 软件:redhat linux as 4 2.6 .9 , 安装系统自带的lm_sensors-2.8.7-2.i386 你也可以从[url]http://www. ...

  8. linux系统cpu温度监控,怎么看cpu温度-ZABBIX监控Linux主机CPU温度

    Linux主机安装Im_sensors [root@localhost ~]# yum install -y lm-sensors [root@localhost ~]# sensors-detect ...

  9. 怎么看服务器cpu温度命令_服务器cpu温度查看

    {"moduleinfo":{"card_count":[{"count_phone":1,"count":1}],&q ...

  10. 剖析CPU温度监控技术

    迄今为止还没有一种cpu散热系统能保证永不失效.失去了散热系统保护伞的"芯",往往会在几秒钟内永远停止"跳动".值得庆幸的是,聪明的工程师们开发出有效的CPU温 ...

最新文章

  1. 【OpenCV 】Sobel 导数/Laplace 算子/Canny 边缘检测
  2. bzoj1266: [AHOI2006]上学路线route
  3. 033_CSS相对定位
  4. 案例 | 撇开虚荣指标,如何策划一场成功的拉新活动?
  5. SAP CRM Fiori应用My Lead的常见问题和解答
  6. 使用Keras和TensorFlow构建深度自动编码器
  7. SpringMVC异常处理流程
  8. 【CodeForces - 697C】Lorenzo Von Matterhorn(二叉树,思维)
  9. Part7 继承与派生 7.4派生类的构造和析构
  10. Glide 这样用,更省内存!!! 1
  11. 离职补偿的N、N+1、2N、2N+1,到底都有什么区别?
  12. 【STM32 .Net MF开发板学习-05】PC通过Modbus协议远程操控开发板
  13. PR转场预设 鼠标拖拽视频画面滑动转场特效PR预设
  14. 虚拟机安装Mac OS系统
  15. VMWare IOS MAC分区教程
  16. 豆瓣读书TOP250书籍信息爬虫脚本
  17. 基于Android的照片分组共享APP设计与实现
  18. 嗅图狗——更新与反馈专贴
  19. linux打开文件乱码
  20. 微信小程序开发笔记 进阶篇④——基于iconfont快速实现icon图标显示

热门文章

  1. 复盘:什么是权重衰减?深度学习权重衰减
  2. 验证二叉树的前序序列化[抽象前序遍历]
  3. c语言 switch语句实例,C语言switch语句
  4. Uniapp Android原生插件开发
  5. python 小数点位数,python如何保留小数点位数
  6. linux触摸屏校准命令,FL2440下触摸屏校准
  7. 合适新手入门的串口屏学习分享
  8. JavaScript文档注释JSDoc注释
  9. 修改文件 火车票买下铺_为什么坐火车时,尽量不要买下铺?过来人用亲身经历告诉你原因...
  10. HKC PG27P3Q 评测