如何访问CPU的热传感器?

fud*_*din 20 c windows hardware sensor hardware-interface

我正在开发软件,我需要访问CPU中的温度传感器并控制它们.

我不太了解硬件接口; 我只知道如何与鼠标接口.我搜索了很多关于它但没有找到任何相关信息或一段代码.

我真的需要在我的软件中添加它.请指导我如何使用C或C++或ASM控制传感器.

Sim*_*ier 19

没有特定的内核驱动程序,除了通过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;
}
Run Code Online (Sandbox Code Playgroud)

和一些测试代码:

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);
}
Run Code Online (Sandbox Code Playgroud)


Ale*_*son 15

我假设您对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/manual/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_STATUSDTS读数和Prime95"就地大FFT(最大热量,功耗,一些RAM测试)"测试之间的相关性.Prime95是ftp://mersenne.org/gimps/p95v266.zip

我没有找到一个公式来从DTS读数中获得"CPU温度"(无论可能意味着什么).

编辑:

引自一个有趣的帖子TJunction Max?#THERMTRIP?#PROCHOT?通过"FGW"(2007年12月):

没有办法在任何寄存器中找到某个处理器的tjmax.因此,没有软件可以读取此值.各种软件开发人员正在做什么,他们只是假定某个处理器的特定连接并将该信息保存在程序中的表中.除此之外,tjmax甚至不是他们追求的正确值.事实上,他们正在寻找TCC活化温度阈值.该温度阈值用于计算当前的绝对核心温度.理论上你可以说:绝对coretemperature = TCC激活温度阈值 - DTS我不得不在理论上说,因为,如上所述,这个TCC激活温度阈值不能由软件读取,必须由程序员承担.在大多数情况下(coretemp,everest,......),根据处理器系列和版本的不同,它们的值为85C或100C.由于该TCC活动温度阈值是在每个处理器单独制造期间校准的,因此对于一个处理器可以是83℃,而对于另一个处理器可以是87℃.考虑到这些程序计算核心温度的方式,你可以自己弄清楚,绝对核心温度是多么准确!在任何公共英特尔文件中都找不到tjmax和"最想要的"TCC活动温度阈值.在英特尔开发者论坛上进行了一些讨论之后,英特尔没有显示任何信息可以提供这些信息.


Mar*_*ett 11

您可以从WMI中的MSAcpi_ThermalZoneTemperature中读取它

使用C++中的WMI有点参与,请参阅MSDN解释和示例

注意:改变原来无益的答案