我正在开发一款软件,需要访问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(Intel Architecture, 32-bit)CPU和Microsoft Windows感兴趣。模型特定寄存器(MSR)IA32_THERM_STATUS
有7位编码的“数字读数(位22:16,只读)——1度摄氏度相对于TCC激活温度。”(见“Intel® 64 and IA-32 Architectures - Software Developer’s Manual - Volume 3 (3A & 3B): System Programming Guide”的“14.5.5.2 Reading the Digital Sensor”http://www.intel.com/Assets/PDF/manual/325384.pdf)。 因此,IA32_THERM_STATUS
将不会给出“CPU温度”,但是会给出某些代理。要读取IA32_THERM_STATUS
寄存器,您可以使用汇编指令rdmsr
,现在rdmsr
不能从用户空间代码调用,因此您需要一些内核空间代码(可能是设备驱动程序?)。您还可以使用相同限制的内在函数__readmsr
(请参见http://msdn.microsoft.com/en-us/library/y55zyfdx(v=VS.100).aspx)。 每个CPU核心都有自己的数字热传感器(DTS),因此需要一些更多代码来获取所有温度(可以使用亲和力掩码吗?请参见Win32 APISetThreadAffinityMask
)。我进行了一些测试,实际上发现了IA32_THERM_STATUS
DTS读数与Prime95“置于大型FFT(最大热量、功率消耗、一些RAM测试)”测试之间的相关性。 Prime95是ftp://mersenne.org/gimps/p95v266.zip。 我没有找到从DTS读数得出“CPU温度”的公式(无论这意味着什么)。 编辑:引用TJunction Max? #THERMTRIP? #PROCHOT?帖子中的有趣帖子由“fgw”(2007年12月)。
CreateService
和dwServiceType
来安装驱动程序,设置为SERVICE_KERNEL_DRIVER
。要分发这样的代码,我是否还需要使用“扩展验证”数字证书对该服务进行签名? - c00000fdALSysIO(64).sys
文件在%temp%
文件夹中。我通过ProcMon
运行了Core Temp.exe
,它并没有创建该文件。 - c00000fdadmin
账户的%temp%
文件夹。(我在查看我的已登录的standard user
账户的%temp%
文件夹。)顺便说一句,我认为将内核驱动程序放入临时文件夹并不是一件好事。但这不是重点。不幸的是,在Win10下,由于更严格的内核驱动程序签名限制,对于大多数开发人员来说,MSR
寄存器方法已经行不通了。 - c00000fd