我正在研究需要訪問CPU中的溫度傳感器並控制它們的軟件。如何訪問CPU的熱傳感器?
我不太瞭解硬件接口;我只知道如何與鼠標交互。我搜索了很多關於它,但沒有找到任何相關的信息或代碼段。
我真的需要在我的軟件中添加這個。請指導我如何控制使用C或C++或ASM的傳感器。
我正在研究需要訪問CPU中的溫度傳感器並控制它們的軟件。如何訪問CPU的熱傳感器?
我不太瞭解硬件接口;我只知道如何與鼠標交互。我搜索了很多關於它,但沒有找到任何相關的信息或代碼段。
我真的需要在我的軟件中添加這個。請指導我如何控制使用C或C++或ASM的傳感器。
您可以從MSAcpi_ThermalZoneTemperature在WMI
從C使用WMI閱讀++是一種參與了一下,看MSDN explanantion and examples
注:更改後的原始無益的答案
我假設你有興趣在一個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並沒有顯示出讓這個 信息可用的跡象。
我能以某種方式改變它的值嗎? – 2011-10-26 11:59:02
@Akito你的意思是寫入寄存器'IA32_THERM_STATUS'?什麼目的? – 2011-10-27 07:03:33
我正在嘗試研究硬件安全漏洞,所以我想知道是否可以通過某種方式更改爲測量的溫度值,以便計算機可能會關閉。 – 2011-10-27 14:15:43
它可能取決於操作系統。在GNU/Linux上,它與ACPI有關。有些硬件甚至沒有物理設備來測量溫度。
這就是我提到Windows的原因。 – 2011-10-24 18:57:19
沒有特定的內核驅動程序,除了通過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);
}
感謝您的回答。 – 2011-10-29 06:21:42
幾乎沒有系統驅動程序實現這個WMI類是非常令人遺憾的,因爲這意味着你必須在大多數時間編寫自己的內核模式驅動程序。 – 2015-10-14 07:19:05
兩個問題:(1)由於某種原因,當我調用這個WMI方法時(從非提升過程)'IEnumWbemClassObject :: Next()'總是返回'80041003'。 (2)即使我將這個進程稱爲提升了WMI調用成功,但返回的值永遠不會改變,假設輸出如下:'((double)temp/10 - 273.15)'。我得到27.85這是錯誤的。任何想法爲什麼? – c00000fd 2017-02-23 05:48:19
非常相關的軟件,但代碼是不可用的。 – 2011-03-18 09:47:17
對不起 - 是的,它只是一些專有DLL的封裝。 – 2011-03-18 15:30:48