讀取CPU核心溫度

將多年前的一個(gè)小驅(qū)動(dòng)搬到簡(jiǎn)書~

CPU溫度簡(jiǎn)述

最近在搞一個(gè)讀取CPU溫度的驅(qū)動(dòng)拓售,網(wǎng)上翻了好多資料凳怨,可發(fā)現(xiàn)全是copy的叉讥,原稿也就兩三篇,可經(jīng)實(shí)踐發(fā)現(xiàn)其中不乏錯(cuò)誤與片面拄养,讓人著實(shí)走彎路离斩,燃起了我要總結(jié)一番的欲望。

這個(gè)驅(qū)動(dòng)搞了一個(gè)多星期瘪匿,總算可以運(yùn)行了跛梗,測(cè)試了幾臺(tái)Intel和AMD的機(jī)器也都測(cè)試通過(guò),測(cè)試對(duì)比用的是CPUID HWMonitor和Core Temp棋弥。

Intel和AMD的CPU中都有溫度傳感器(DTS)核偿,每個(gè)核心都有一個(gè),溫度就是由此獲取來(lái)的顽染,多核cpu可以使用 SetProcessAffinityMask API 來(lái)指定執(zhí)行的CPU漾岳。

首先是利用CPUID來(lái)區(qū)分是Intel型號(hào)還是AMD型號(hào),利用匯編和函數(shù)都可實(shí)現(xiàn)粉寞,考慮到64位系統(tǒng)不支持嵌入?yún)R編尼荆,所以還是直接利用API函數(shù)就行。

CPUID其實(shí)就是對(duì)eax執(zhí)行cpuid指令唧垦,返回信息儲(chǔ)存在eax,ebx,ecx,edx中捅儒,令eax=0,可將CPU廠商信息返回在ebx,ecx,edx中,

    int CPUInfo[4];

    __cpuid(CPUInfo,0); 

Intel信息字符串為GenuineIntel巧还,AMD為AuthenticAMD鞭莽,只判斷前4個(gè)字符就可以,只需與CPUInfo[1](ebx)比較就可得出型號(hào)麸祷。

Intel

接下來(lái)說(shuō)如何獲取溫度澎怒,先從簡(jiǎn)單的說(shuō)起,Intel實(shí)現(xiàn)起來(lái)比較簡(jiǎn)單:

先以eax=0 執(zhí)行 cpuid 檢測(cè) eax 支持的最大命令數(shù)阶牍,如果小于6就肯定不支持DTS喷面。然后以eax=6 執(zhí)行 cpuid, 然后測(cè)試 eax 第一位是否為1,如果為1表示CPU支持DTS走孽。

讀取DTS:以 ecx=0x1A2 執(zhí)行 rdmsr 指令, 測(cè)試 eax 的第30位是否為 1, 如果為 1 表示溫度計(jì)算的初始值為 85 度否則表示從100度開始計(jì)算,這個(gè)值稱為 Tjunction.

eax=__readmsr(0x01A2)

然后以 ecx=0x19c 執(zhí)行 rdmsr 指令, eax 的 16-23 位為表示當(dāng)前DTS 值,當(dāng)前溫度要以下面公式計(jì)算.
當(dāng)前cpu溫度 = Tjunction - DTS

注意 signature 為 0x6f1乖酬, 0x6f0的 CPU DTS 值直接代表當(dāng)前溫度而不用Tjunction 相減. 而 signature 小于等于 0x6f4 的 Tjunction 一直為100。

AMD

AMD就比較惡心了融求,研究了挺長(zhǎng)時(shí)間:

AMD溫度存儲(chǔ)在NB寄存器中,這是一個(gè)熱傳感寄存器算撮。AMD的CPU分為K8和K10生宛,K8的溫度存儲(chǔ)在這個(gè)寄存器的23-14位,K10的在31-21位肮柜。

要訪問(wèn)這個(gè)狀態(tài)寄存器陷舅,需要對(duì)PCI進(jìn)行讀寫。
先介紹倆個(gè)PCI用到的寄存器审洞,CF8h和CFCh
CF8h: 存放配置空間的地址(CONFIG-ADDRESS)
CFCh: 保存配置空間的讀寫數(shù)據(jù)(CONFIG-DATA)
這兩個(gè)空間對(duì)應(yīng)于PCI橋路的兩個(gè)寄存器莱睁,當(dāng)橋路看到CPU在局部總線對(duì)這兩個(gè) I/O空間進(jìn)行雙字操作時(shí),就將該I/O操作轉(zhuǎn)變?yōu)镻CI總線的配置操作芒澜。

溫度讀取:
如果是K8的話仰剿,可以忽略低倆位,讀取23-16就可以了痴晦,當(dāng)然也可以讀23-14南吮,然后\4或者>>2;
如果是K10的話誊酌,那就讀取31-21

如何判斷K8部凑,K10:

__cpuid(CPUInfo,1); //cpuid執(zhí)行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

溫度的計(jì)算公式:

K8 Temp = Value - 49'.   49這個(gè)值需要修正的:if (model >= 0x69 && model != 0xc1 && model != 0x6c 
&& model != 0x7c)  temp=Value-49+21;
K10 Temp = Value / 8'.

IO訪問(wèn)PCI總線設(shè)備配置空間:
配置空間地址寄存器的格式:
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后,可以這么來(lái)構(gòu)造配置空間地址寄存器:
IOADDR = 0x80000000+bus*0x10000 +(device*8)*0x100 + uFunction&0x07 + register number&~3;
為什么需要0x80000000呢敷搪,因?yàn)?br> 當(dāng)CPU發(fā)出對(duì)I/O空間CFCh的操作時(shí)兴想,PCI橋路將檢查配置空間地址寄存器CF8h的31位。如果為1赡勘,就在PCI總線上產(chǎn)生一個(gè)相應(yīng)的配置空間讀或?qū)懖僮鳎?x80000000就是使配置空間地址寄存器為1嫂便。
經(jīng)過(guò)上面的討論后,可以寫成

#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后就可以通過(guò)IO指令來(lái)讀寫了践樱。

對(duì)于K8厂画, uAddress為0xE4,對(duì)于K10 uAddress為0xA4

怎樣獲取uBus拷邢, uDevice袱院, uFunction:
從上面知道GetDevice需要 uBus, uDevice瞭稼, uFunction的忽洛。
可以掃描PCI總線來(lái)獲取,對(duì)于AMD K8來(lái)說(shuō)环肘,設(shè)備ID為0x1103欲虚,對(duì)于K10來(lái)說(shuō),設(shè)備ID為0x1203悔雹。 二者的uFunction都為3.
通過(guò)掃描PCI總線复哆,匹配設(shè)備ID來(lái)獲取。

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函數(shù)

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;
}

然后進(jìn)行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);
?著作權(quán)歸作者所有,轉(zhuǎn)載或內(nèi)容合作請(qǐng)聯(lián)系作者
  • 序言:七十年代末梯找,一起剝皮案震驚了整個(gè)濱河市,隨后出現(xiàn)的幾起案子莱没,更是在濱河造成了極大的恐慌初肉,老刑警劉巖,帶你破解...
    沈念sama閱讀 221,548評(píng)論 6 515
  • 序言:濱河連續(xù)發(fā)生了三起死亡事件饰躲,死亡現(xiàn)場(chǎng)離奇詭異牙咏,居然都是意外死亡,警方通過(guò)查閱死者的電腦和手機(jī)嘹裂,發(fā)現(xiàn)死者居然都...
    沈念sama閱讀 94,497評(píng)論 3 399
  • 文/潘曉璐 我一進(jìn)店門妄壶,熙熙樓的掌柜王于貴愁眉苦臉地迎上來(lái),“玉大人寄狼,你說(shuō)我怎么就攤上這事丁寄“碧剩” “怎么了?”我有些...
    開封第一講書人閱讀 167,990評(píng)論 0 360
  • 文/不壞的土叔 我叫張陵伊磺,是天一觀的道長(zhǎng)盛正。 經(jīng)常有香客問(wèn)我,道長(zhǎng)屑埋,這世上最難降的妖魔是什么豪筝? 我笑而不...
    開封第一講書人閱讀 59,618評(píng)論 1 296
  • 正文 為了忘掉前任,我火速辦了婚禮摘能,結(jié)果婚禮上续崖,老公的妹妹穿的比我還像新娘。我一直安慰自己团搞,他們只是感情好严望,可當(dāng)我...
    茶點(diǎn)故事閱讀 68,618評(píng)論 6 397
  • 文/花漫 我一把揭開白布。 她就那樣靜靜地躺著逻恐,像睡著了一般像吻。 火紅的嫁衣襯著肌膚如雪。 梳的紋絲不亂的頭發(fā)上复隆,一...
    開封第一講書人閱讀 52,246評(píng)論 1 308
  • 那天萧豆,我揣著相機(jī)與錄音,去河邊找鬼昏名。 笑死,一個(gè)胖子當(dāng)著我的面吹牛阵面,可吹牛的內(nèi)容都是我干的轻局。 我是一名探鬼主播,決...
    沈念sama閱讀 40,819評(píng)論 3 421
  • 文/蒼蘭香墨 我猛地睜開眼样刷,長(zhǎng)吁一口氣:“原來(lái)是場(chǎng)噩夢(mèng)啊……” “哼仑扑!你這毒婦竟也來(lái)了?” 一聲冷哼從身側(cè)響起置鼻,我...
    開封第一講書人閱讀 39,725評(píng)論 0 276
  • 序言:老撾萬(wàn)榮一對(duì)情侶失蹤镇饮,失蹤者是張志新(化名)和其女友劉穎,沒(méi)想到半個(gè)月后箕母,有當(dāng)?shù)厝嗽跇淞掷锇l(fā)現(xiàn)了一具尸體储藐,經(jīng)...
    沈念sama閱讀 46,268評(píng)論 1 320
  • 正文 獨(dú)居荒郊野嶺守林人離奇死亡,尸身上長(zhǎng)有42處帶血的膿包…… 初始之章·張勛 以下內(nèi)容為張勛視角 年9月15日...
    茶點(diǎn)故事閱讀 38,356評(píng)論 3 340
  • 正文 我和宋清朗相戀三年嘶是,在試婚紗的時(shí)候發(fā)現(xiàn)自己被綠了钙勃。 大學(xué)時(shí)的朋友給我發(fā)了我未婚夫和他白月光在一起吃飯的照片。...
    茶點(diǎn)故事閱讀 40,488評(píng)論 1 352
  • 序言:一個(gè)原本活蹦亂跳的男人離奇死亡聂喇,死狀恐怖辖源,靈堂內(nèi)的尸體忽然破棺而出,到底是詐尸還是另有隱情,我是刑警寧澤克饶,帶...
    沈念sama閱讀 36,181評(píng)論 5 350
  • 正文 年R本政府宣布酝蜒,位于F島的核電站,受9級(jí)特大地震影響矾湃,放射性物質(zhì)發(fā)生泄漏亡脑。R本人自食惡果不足惜,卻給世界環(huán)境...
    茶點(diǎn)故事閱讀 41,862評(píng)論 3 333
  • 文/蒙蒙 一洲尊、第九天 我趴在偏房一處隱蔽的房頂上張望远豺。 院中可真熱鬧,春花似錦坞嘀、人聲如沸躯护。這莊子的主人今日做“春日...
    開封第一講書人閱讀 32,331評(píng)論 0 24
  • 文/蒼蘭香墨 我抬頭看了看天上的太陽(yáng)棺滞。三九已至,卻和暖如春矢渊,著一層夾襖步出監(jiān)牢的瞬間继准,已是汗流浹背。 一陣腳步聲響...
    開封第一講書人閱讀 33,445評(píng)論 1 272
  • 我被黑心中介騙來(lái)泰國(guó)打工矮男, 沒(méi)想到剛下飛機(jī)就差點(diǎn)兒被人妖公主榨干…… 1. 我叫王不留移必,地道東北人。 一個(gè)月前我還...
    沈念sama閱讀 48,897評(píng)論 3 376
  • 正文 我出身青樓毡鉴,卻偏偏與公主長(zhǎng)得像崔泵,于是被迫代替她去往敵國(guó)和親。 傳聞我的和親對(duì)象是個(gè)殘疾皇子猪瞬,可洞房花燭夜當(dāng)晚...
    茶點(diǎn)故事閱讀 45,500評(píng)論 2 359

推薦閱讀更多精彩內(nèi)容

  • 組件 計(jì)算機(jī)是一種數(shù)據(jù)處理設(shè)備憎瘸,它由CPU和內(nèi)存以及外部設(shè)備組成。CPU負(fù)責(zé)數(shù)據(jù)處理陈瘦,內(nèi)存負(fù)責(zé)存儲(chǔ)幌甘,外部設(shè)備負(fù)責(zé)數(shù)...
    哆啦灬少A夢(mèng)閱讀 1,594評(píng)論 1 2
  • 有時(shí)候購(gòu)買的商品,屬性很多痊项,想做成表格進(jìn)行篩選锅风。自然用技術(shù)宅的爬蟲方式做了 ```python # -*- ...
    超哥__閱讀 4,248評(píng)論 0 8
  • 原文地址:C語(yǔ)言函數(shù)調(diào)用棧(一)C語(yǔ)言函數(shù)調(diào)用棧(二) 0 引言 程序的執(zhí)行過(guò)程可看作連續(xù)的函數(shù)調(diào)用。當(dāng)一個(gè)函數(shù)執(zhí)...
    小豬啊嗚閱讀 4,624評(píng)論 1 19
  • 文 ‖ 清 ××說(shuō):感人的文章千篇一律,有趣的靈魂萬(wàn)里挑一塞弊。 我喜歡的靈魂漱逸,可以列一個(gè)清單泪姨。馬克思,曾國(guó)藩饰抒,書磊肮砾,...
    清揚(yáng)看圖史閱讀 304評(píng)論 2 1
  • 簡(jiǎn)介:公子扶蘇,始皇長(zhǎng)子袋坑,因反對(duì)坑儒焚書被流放……李蓉一遍又一遍的念著贏扶蘇的生平仗处,眼角淚光若隱若現(xiàn)。書里書外隔了...
    糖紫芯閱讀 1,245評(píng)論 23 16