我正在开发需要访问 CPU 中的温度传感器并控制它们的软件。
我不太了解硬件接口;我只知道如何与鼠标交互。我用谷歌搜索了很多关于它的信息,但没有找到任何相关信息或代码。
我真的需要在我的软件中添加这个。请指导我如何使用 C 或 C++ 或 ASM 控制传感器。
我正在开发需要访问 CPU 中的温度传感器并控制它们的软件。
我不太了解硬件接口;我只知道如何与鼠标交互。我用谷歌搜索了很多关于它的信息,但没有找到任何相关信息或代码。
我真的需要在我的软件中添加这个。请指导我如何使用 C 或 C++ 或 ASM 控制传感器。
如果没有特定的内核驱动程序,除了通过 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;
}
和一些测试代码:
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);
}
我假设您对 IA-32(英特尔架构,32 位)CPU 和 Microsoft Windows 感兴趣。
型号特定寄存器 (MSR)IA32_THERM_STATUS
有 7 位编码“数字读数(位 22:16,RO)- 相对于 TCC 激活温度的 1 摄氏度的数字温度读数”。(请参阅“英特尔® 64 和 IA-32 架构 - 软件开发人员手册 - 第 3 卷(3A 和 3B):系统编程指南”中的“14.5.5.2 读取数字传感器” http://www.intel.com/Assets/ PDF/手册/325384.pdf)。
所以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 温度”(无论这意味着什么)的公式。
编辑:
引用有趣的帖子TJunction Max?#THERMTRIP?#PROCHOT?“ fgw”(2007 年 12 月):
无法在任何寄存器中找到某个处理器的 tjmax。因此没有软件可以读取这个值。各种软件开发人员正在做什么,他们只是假设某个处理器的某个连接并将此信息保存在程序内的一个表中。除此之外,tjmax 甚至不是他们所追求的正确值。事实上,他们正在寻找 TCC 激活温度阈值。此温度阈值用于计算当前绝对核心温度。理论上你可以说:绝对核心温度 = TCC 激活温度阈值 - DTS 我不得不在理论上说,因为如上所述,这个 TCC 激活温度阈值不能由软件读取,必须由程序员承担。在大多数情况下(coretemp、everest、... ) 根据处理器系列和版本,它们假定值为 85C 或 100C。由于此 TCC 激活温度阈值在每个处理器的制造过程中单独校准,因此一个处理器可能为 83C,但另一个处理器可能为 87C。考虑到这些程序计算核心温度的方式,您可以自己计算出绝对核心温度的准确度!在任何公开的英特尔文档中都找不到 tjmax 和“最想要的”TCC 激活温度阈值。在英特尔开发者论坛上进行了一些讨论之后,英特尔没有迹象表明可以提供此信息。一个处理器可能是 83C,但另一个处理器可能是 87C。考虑到这些程序计算核心温度的方式,您可以自己计算出绝对核心温度的准确度!在任何公开的英特尔文档中都找不到 tjmax 和“最想要的”TCC 激活温度阈值。在英特尔开发者论坛上进行了一些讨论之后,英特尔没有迹象表明可以提供此信息。一个处理器可能是 83C,但另一个处理器可能是 87C。考虑到这些程序计算核心温度的方式,您可以自己计算出绝对核心温度的准确度!在任何公开的英特尔文档中都找不到 tjmax 和“最想要的”TCC 激活温度阈值。在英特尔开发者论坛上进行了一些讨论之后,英特尔没有迹象表明可以提供此信息。
这可能取决于操作系统。在 GNU/Linux 上,它与 ACPI 有关。有些硬件甚至没有测量温度的物理设备。