C语言 如何访问 CPU 的热传感器?
声明:本页面是StackOverFlow热门问题的中英对照翻译,遵循CC BY-SA 4.0协议,如果您需要使用它,必须同样遵循CC BY-SA许可,注明原文地址和作者信息,同时你必须将它归于原作者(不是我):StackOverFlow
原文地址: http://stackoverflow.com/questions/5327203/
Warning: these are provided under cc-by-sa 4.0 license. You are free to use/share it, But you must attribute it to the original authors (not me):
StackOverFlow
How to access CPU's heat sensors?
提问by fuddin
I am working on software in which I need to access the temperature sensors in the CPU and get control over them.
我正在开发需要访问 CPU 中的温度传感器并控制它们的软件。
I don't know much hardware interfacing; I just know how to interface with the mouse. I have googled a lot about it but failed to find any relevant information or piece of code.
我不太了解硬件接口;我只知道如何与鼠标交互。我在谷歌上搜索了很多,但没有找到任何相关信息或代码段。
I really need to add this in my software. Please guide me how to have the control over the sensors using C or C++ or ASM.
我真的需要在我的软件中添加这个。请指导我如何使用 C 或 C++ 或 ASM 控制传感器。
回答by Simon Mourier
Without a specific kernel driver, it's difficult to query the temperature, other than through WMI. Here is a piece of C code that does it, based on WMI's MSAcpi_ThermalZoneTemperature class:
没有特定的内核驱动程序,除了通过 WMI 之外,很难查询温度。这是一段基于 WMI 的 MSAcpi_ThermalZoneTemperature 类的 C 代码:
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;
}
and some test code:
和一些测试代码:
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);
}
回答by Alessandro Jacopson
I assume you are interested in a IA-32 (Intel Architecture, 32-bit) CPU and Microsoft Windows.
我假设您对 IA-32(英特尔架构,32 位)CPU 和 Microsoft Windows 感兴趣。
The Model Specific Register (MSR) IA32_THERM_STATUShas 7 bits encoding the "Digital Readout (bits 22:16, RO) — Digital temperature reading in 1 degree Celsius relative to the TCC activation temperature." (see "14.5.5.2 Reading the Digital Sensor" in "Intel? 64 and IA-32 Architectures - Software Developer's Manual - Volume 3 (3A & 3B): System Programming Guide" http://www.intel.com/Assets/PDF/manual/325384.pdf).
模型特定寄存器 (MSR)IA32_THERM_STATUS有 7 位编码“数字读数(位 22:16,RO)— 相对于 TCC 激活温度的 1 摄氏度数字温度读数”。(参见“Intel? 64 and IA-32 Architectures - Software Developer's Manual - Volume 3 (3A & 3B): System Programming Guide”中的“14.5.5.2 读取数字传感器” http://www.intel.com/Assets/ PDF/手册/325384.pdf)。
So IA32_THERM_STATUSwill not give you the "CPU temperature" but some proxy for it.
所以IA32_THERM_STATUS不会给你“CPU温度”,而是它的一些代理。
In order to read the IA32_THERM_STATUSregister you use the asm instruction rdmsr, now rdmsrcannot be called from user space code and so you need some kernel space code (maybe a device driver?).
为了读取IA32_THERM_STATUS您使用 asm 指令的寄存器rdmsr,现在rdmsr不能从用户空间代码调用,因此您需要一些内核空间代码(可能是设备驱动程序?)。
You can also use the intrinsic __readmsr(see http://msdn.microsoft.com/en-us/library/y55zyfdx(v=VS.100).aspx) which has anyway the same limitation: "This function is only available in kernel mode".
您还可以使用内在的__readmsr(请参阅http://msdn.microsoft.com/en-us/library/y55zyfdx(v=VS.100).aspx),它具有相同的限制:“此功能仅在内核中可用模式”。
Every CPU cores has its own Digital Thermal Sensors (DTS) and so some more code is needed to get all the temperatures (maybe with the affinity mask? see Win32 API SetThreadAffinityMask).
每个 CPU 内核都有自己的数字热传感器 (DTS),因此需要更多代码来获取所有温度(可能带有亲和掩码?请参阅 Win32 API SetThreadAffinityMask)。
I did some tests and actually found a correlation between the IA32_THERM_STATUSDTS readouts and the Prime95 "In-place large FFTs (maximum heat, power consumption, some RAM tested)" test. Prime95 is ftp://mersenne.org/gimps/p95v266.zip
我做了一些测试,实际上发现了IA32_THERM_STATUSDTS 读数与 Prime95“就地大型 FFT(最大热量、功耗、一些 RAM 测试)”测试之间的相关性。Prime95 是ftp://mersenne.org/gimps/p95v266.zip
I did not find a formula to get the "CPU temperature" (whatever that may mean) from the DTS readout.
我没有找到从 DTS 读数中获取“CPU 温度”(无论这意味着什么)的公式。
Edit:
编辑:
Quoting from an interesting post TJunction Max? #THERMTRIP? #PROCHOT?by "fgw"(December 2007):
引用一个有趣的帖子TJunction Max?#THERMTRIP?#PROCHOT?来自“fgw”(2007 年 12 月):
there is no way to find tjmax of a certain processor in any register. thus no software can read this value. what various software developers are doing, is they simply assume a certain tjunction for a certain processor and hold this information in a table within the program. besides that, tjmax is not even the correct value they are after. in fact they are looking for TCC activacion temperature threshold. this temperature threshold is used to calculate current absolute coretemperatures from. theoretical you can say: absolute coretemperature = TCC activacion temperature threshold - DTS i had to say theoretically because, as stated above, this TCC activacion temperature threshold cant be read by software and has to be assumed by the programmer. in most situations (coretemp, everest, ...) they assume a value of 85C or 100C depending on processor family and revision. as this TCC activacion temperature threshold is calibrated during manufacturing individually per processor, it could be 83C for one processor but may be 87C for the other. taking into account the way those programms are calculating coretemperatures, you can figure out at your own, how accurate absolute coretemperatures are! neither tjmax nor the "most wanted" TCC activacion temperature threshold can be found in any public intel documents. following some discussions over on the intel developer forum, intel shows no sign to make this information available.
无法在任何寄存器中找到某个处理器的 tjmax。因此没有软件可以读取这个值。各种软件开发人员正在做的是,他们只是假设某个处理器的某个连接点,并将此信息保存在程序中的表中。除此之外, tjmax 甚至不是他们所追求的正确值。事实上,他们正在寻找 TCC 激活温度阈值。此温度阈值用于计算当前绝对核心温度。理论上你可以说:绝对核心温度 = TCC 激活温度阈值 - DTS 我不得不在理论上说,因为如上所述,这个 TCC 激活温度阈值不能被软件读取,必须由程序员假设。在大多数情况下(coretemp、everest、... ) 它们假定值为 85C 或 100C,具体取决于处理器系列和版本。由于此 TCC 激活温度阈值是在每个处理器的制造过程中单独校准的,因此一个处理器可能为 83C,而另一个处理器可能为 87C。考虑到这些程序计算核心温度的方式,您可以自己计算出绝对核心温度的准确程度!在任何公开的英特尔文档中都找不到 tjmax 和“最想要的”TCC 激活温度阈值。在英特尔开发者论坛上进行了一些讨论后,英特尔没有迹象表明可以提供此信息。一个处理器可能是 83C,但另一个处理器可能是 87C。考虑到这些程序计算核心温度的方式,您可以自己计算出绝对核心温度的准确程度!在任何公开的英特尔文档中都找不到 tjmax 和“最想要的”TCC 激活温度阈值。在英特尔开发者论坛上进行了一些讨论后,英特尔没有迹象表明可以提供此信息。一个处理器可能是 83C,但另一个处理器可能是 87C。考虑到这些程序计算核心温度的方式,您可以自己计算出绝对核心温度的准确程度!在任何公开的英特尔文档中都找不到 tjmax 和“最想要的”TCC 激活温度阈值。在英特尔开发者论坛上进行了一些讨论后,英特尔没有迹象表明可以提供此信息。
回答by Martin Beckett
You can read it from the MSAcpi_ThermalZoneTemperature in WMI
您可以从 WMI 中的 MSAcpi_ThermalZoneTemperature 读取它
Using WMI from C++ is a bit involved, see MSDN explanantion and examples
从 C++ 使用 WMI 有点复杂,请参阅MSDN 说明和示例
note: changed original unhelpful answer
注意:更改了原来无用的答案
回答by Basile Starynkevitch
It probably depends upon the operating system. On GNU/Linux, it is related to ACPI. And some hardware don't even have the physical devices to measure the temperature.
这可能取决于操作系统。在 GNU/Linux 上,它与 ACPI 相关。有些硬件甚至没有物理设备来测量温度。

