2011-03-16 101 views
18

我正在研究需要訪問CPU中的溫度傳感器並控制它們的軟件。如何訪問CPU的熱傳感器?

我不太瞭解硬件接口;我只知道如何與鼠標交互。我搜索了很多關於它,但沒有找到任何相關的信息或代碼段。

我真的需要在我的軟件中添加這個。請指導我如何控制使用C或C++或ASM的傳感器。

回答

11

您可以從MSAcpi_ThermalZoneTemperature在WMI

從C使用WMI閱讀++是一種參與了一下,看MSDN explanantion and examples

注:更改後的原始無益的答案

+0

非常相關的軟件,但代碼是不可用的。 – 2011-03-18 09:47:17

+0

對不起 - 是的,它只是一些專有DLL的封裝。 – 2011-03-18 15:30:48

15

我假設你有興趣在一個IA -32(英特爾架構,32位)CPU和Microsoft Windows。

型號特定寄存器(MSR)IA32_THERM_STATUS具有7位編碼「數字讀數(位22:16,RO) - 相對於TCC激活溫度1攝氏度的數字溫度讀數」。 (請參閱「英特爾®64和IA-32架構 - 軟件開發人員手冊 - 第3卷(系統編程指南」http://www.intel.com/Assets/PDF/manual/325384.pdf)「中的」14.5.5.2讀取數字傳感器「。

因此IA32_THERM_STATUS不會給你「CPU溫度」,但它的一些代理。

爲了讀取IA32_THERM_STATUS註冊使用ASM指令rdmsr,現在rdmsr不能從用戶空間代碼調用,所以你需要一些內核空間代碼(可能是設備驅動程序?)。

您也可以使用固有的__readmsr(請參見http://msdn.microsoft.com/en-us/library/y55zyfdx(v=VS.100).aspx),它有任何相同的限制:「此功能僅在內核模式下可用」。每個CPU內核都有自己的數字熱傳感器(DTS),因此需要更多代碼來獲得所有溫度(可能使用親和性掩碼?參見Win32 API SetThreadAffinityMask)。

我做了一些測試,實際上發現IA32_THERM_STATUS DTS讀數和Prime95「就地大FFT(最大熱量,功耗,一些RAM測試)」測試之間的相關性。 Prime95是ftp://mersenne.org/gimps/p95v266.zip

我沒有找到從DTS讀數中獲得「CPU溫度」(無論這可能是什麼意思)的公式。

編輯:

"fgw"(2007年12月)從一個有趣的帖子TJunction Max? #THERMTRIP? #PROCHOT?報價:

沒有辦法找到TJMAX某個處理器的任何寄存器中。 因此沒有軟件可以讀取這個值。各種軟件開發人員正在做什麼,他們是否簡單地假定某個處理器的特定連接,並將該信息保存在程序中的表格中。除此之外,tjmax甚至不是它們之後的正確值。在 事實上,他們正在尋找TCC激活溫度閾值。這個溫度閾值用來計算當前絕對溫度。理論上你可以這樣說:絕對溫度= TCC活化溫度閾值-DTS我不得不 理論上說,因爲如上所述,這個TCC活化溫度閾值不能由軟件讀取,並且必須由程序員假設爲 。在大多數情況下(coretemp,everest,...),它們根據處理器系列和 修訂版假定值爲85C或100C。由於該TCC活化溫度閾值在每個處理器單獨製造期間被校準爲 ,所以對於 一個處理器可以是83C,但對於另一個可以是87C。考慮到這些程序正在計算核心溫度的 方式,你可以自己計算出 ,絕對核心溫度有多精確!在任何公共英特爾文檔中均未找到tjmax或「最需要的」TCC活動溫度閾值 。在intel開發人員論壇上討論了一些關於 的討論,intel並沒有顯示出讓這個 信息可用的跡象。

+0

我能以某種方式改變它的值嗎? – 2011-10-26 11:59:02

+0

@Akito你的意思是寫入寄存器'IA32_THERM_STATUS'?什麼目的? – 2011-10-27 07:03:33

+0

我正在嘗試研究硬件安全漏洞,所以我想知道是否可以通過某種方式更改爲測量的溫度值,以便計算機可能會關閉。 – 2011-10-27 14:15:43

0

它可能取決於操作系統。在GNU/Linux上,它與ACPI有關。有些硬件甚至沒有物理設備來測量溫度。

+0

這就是我提到Windows的原因。 – 2011-10-24 18:57:19

17

沒有特定的內核驅動程序,除了通過WMI之外,很難查詢溫度。下面是一段C代碼,做它,基於WMI的MSAcpi_ThermalZoneTemperature類:

HRESULT GetCpuTemperature(LPLONG pTemperature) 
{ 
    if (pTemperature == NULL) 
     return E_INVALIDARG; 

    *pTemperature = -1; 
    HRESULT ci = CoInitialize(NULL); // needs comdef.h 
    HRESULT hr = CoInitializeSecurity(NULL, -1, NULL, NULL, RPC_C_AUTHN_LEVEL_DEFAULT, RPC_C_IMP_LEVEL_IMPERSONATE, NULL, EOAC_NONE, NULL); 
    if (SUCCEEDED(hr)) 
    { 
     IWbemLocator *pLocator; // needs Wbemidl.h & Wbemuuid.lib 
     hr = CoCreateInstance(CLSID_WbemAdministrativeLocator, NULL, CLSCTX_INPROC_SERVER, IID_IWbemLocator, (LPVOID*)&pLocator); 
     if (SUCCEEDED(hr)) 
     { 
      IWbemServices *pServices; 
      BSTR ns = SysAllocString(L"root\\WMI"); 
      hr = pLocator->ConnectServer(ns, NULL, NULL, NULL, 0, NULL, NULL, &pServices); 
      pLocator->Release(); 
      SysFreeString(ns); 
      if (SUCCEEDED(hr)) 
      { 
       BSTR query = SysAllocString(L"SELECT * FROM MSAcpi_ThermalZoneTemperature"); 
       BSTR wql = SysAllocString(L"WQL"); 
       IEnumWbemClassObject *pEnum; 
       hr = pServices->ExecQuery(wql, query, WBEM_FLAG_RETURN_IMMEDIATELY | WBEM_FLAG_FORWARD_ONLY, NULL, &pEnum); 
       SysFreeString(wql); 
       SysFreeString(query); 
       pServices->Release(); 
       if (SUCCEEDED(hr)) 
       { 
        IWbemClassObject *pObject; 
        ULONG returned; 
        hr = pEnum->Next(WBEM_INFINITE, 1, &pObject, &returned); 
        pEnum->Release(); 
        if (SUCCEEDED(hr)) 
        { 
         BSTR temp = SysAllocString(L"CurrentTemperature"); 
         VARIANT v; 
         VariantInit(&v); 
         hr = pObject->Get(temp, 0, &v, NULL, NULL); 
         pObject->Release(); 
         SysFreeString(temp); 
         if (SUCCEEDED(hr)) 
         { 
          *pTemperature = V_I4(&v); 
         } 
         VariantClear(&v); 
        } 
       } 
      } 
      if (ci == S_OK) 
      { 
       CoUninitialize(); 
      } 
     } 
    } 
    return hr; 
} 

和一些測試代碼:

HRESULT GetCpuTemperature(LPLONG pTemperature); 

int _tmain(int argc, _TCHAR* argv[]) 
{ 
    LONG temp; 
    HRESULT hr = GetCpuTemperature(&temp); 
    printf("hr=0x%08x temp=%i\n", hr, temp); 
} 
+0

感謝您的回答。 – 2011-10-29 06:21:42

+0

幾乎沒有系統驅動程序實現這個WMI類是非常令人遺憾的,因爲這意味着你必須在大多數時間編寫自己的內核模式驅動程序。 – 2015-10-14 07:19:05

+0

兩個問題:(1)由於某種原因,當我調用這個WMI方法時(從非提升過程)'IEnumWbemClassObject :: Next()'總是返回'80041003'。 (2)即使我將這個進程稱爲提升了WMI調用成功,但返回的值永遠不會改變,假設輸出如下:'((double)temp/10 - 273.15)'。我得到27.85這是錯誤的。任何想法爲什麼? – c00000fd 2017-02-23 05:48:19