web-dev-qa-db-fra.com

Obtenez la température du processeur

Je veux obtenir la température du processeur. Voici ce que j'ai fait en utilisant C++ et WMI. Je lis MSAcpi_ThermalZoneTemperature, mais c'est toujours la même chose et ce n'est pas du tout la température du processeur.

Existe-t-il un moyen d'obtenir la température réelle du CPU sans avoir à écrire de pilotes? Ou existe-t-il des bibliothèques que je peux utiliser? Merci d'avance.

#define _WIN32_DCOM
#include <iostream>
using namespace std;
#include <comdef.h>
#include <Wbemidl.h>

#pragma comment(lib, "wbemuuid.lib")

HRESULT GetCpuTemperature(LPLONG pTemperature)
{
        if (pTemperature == NULL)
                return E_INVALIDARG;

        *pTemperature = -1;
        HRESULT ci = CoInitialize(NULL);
        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;
                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;
}

int main(int argc, char **argv)
{
        LONG temp;
        GetCpuTemperature(&temp);
        printf("temp=%lf\n", ((double)temp / 10 - 273.15));
        getc(stdin);
        return 0;
}
24
Johnny Mnemonic

À vrai dire, cela dépend du matériel.

Une bibliothèque qui fonctionne sur la plupart du matériel est OpenHardwareMonitorLib, malheureusement, elle n'a pas de documentation et n'existe pas vraiment en tant que logiciel indépendant. il fait partie d'un logiciel open source appelé "Open Hardware Monitor". Heureusement, vous pouvez obtenir un DLL et l'interface graphique est complètement séparée à 100% du backend réel qui est OpenHardwareMonitorLib. Malheureusement, cela se fait dans .NET C Sharp et bien sûr, ne fonctionne que pour Windows. Lire ce post sur la façon de l'utiliser à partir de C++

Comment appeler une bibliothèque C # depuis Native C++ (en utilisant C++\CLI et IJW)

Donc, étant donné qu'il n'a pas de documents, cela peut être un peu difficile à travailler. Après avoir lu la source pendant un certain temps, voici ma position:

using OpenHardwareMonitor.Hardware;
...
        float? cpu_temperature_celcius = null;
        Computer computer= new Computer();
        computer.CPUEnabled = true;
        computer.Open();
        foreach (IHardware hardware in computer.Hardware)
            if (hardware.HardwareType == HardwareType.CPU)
                foreach (ISensor sensor in hardware.Sensors)
                    if (sensor.SensorType == SensorType.Temperature)
                        cpu_temperature_celcius = sensor.Value;

Ce code #C est vérifié pour obtenir la température d'un processeur Intel Haswell dans Celcius et fonctionnera probablement pour la plupart des autres processeurs AMD et Intel. OpenHardwareMonitorLib.dll est nécessaire. Vous pouvez le compiler depuis source

Vous pouvez obtenir beaucoup d'autres informations sur le système avec cette bibliothèque.

Notez que le CPU de l'utilisateur peut avoir plusieurs capteurs de température. Par exemple, un capteur de température pour chaque cœur, alors ne prenez pas toujours le dernier comme je l'ai fait dans l'exemple ci-dessus.

Bonne chance.

2
tomer zeitune

Le lien vers la source pour OpenHardwareMonitorLib fourni dans réponse de Tomer illustre ce qui doit se produire à un bas niveau pour lire ces informations sur différents types de CPU. Par exemple, la classe IntelCP définit certains registres spécifiques au modèle:

private const uint IA32_THERM_STATUS_MSR = 0x019C;
private const uint IA32_TEMPERATURE_TARGET = 0x01A2;
private const uint IA32_PERF_STATUS = 0x0198;
private const uint MSR_PLATFORM_INFO = 0xCE;
private const uint IA32_PACKAGE_THERM_STATUS = 0x1B1;
private const uint MSR_RAPL_POWER_UNIT = 0x606;
private const uint MSR_PKG_ENERY_STATUS = 0x611;
private const uint MSR_DRAM_ENERGY_STATUS = 0x619;
private const uint MSR_PP0_ENERY_STATUS = 0x639;
private const uint MSR_PP1_ENERY_STATUS = 0x641;

Ceux-ci sont directement issus des documents d'Intel comme Surveillance du processeur avec DTS/PECI (section 16 "Accès MSR direct"). Ils peuvent également être documentés dans le Manuel du développeur de logiciels Intel, mais je n'ai pas vérifié.

OpenHardwareMonitorLib utilise Rdmsr et RdmsrTx pour extraire les valeurs de température des MSR d'intérêt.

Le code AMD correspondant semble obtenir des informations similaires d'un registre PCI. AMD aura une documentation équivalente quelque part qui le définira.

Dans les deux cas, il s'agit, par définition, de la façon dont le matériel expose les informations sur ses capteurs de température. Vous pouvez utiliser une bibliothèque comme celle-ci et elle le fera sous le capot, ou vous pouvez écrire votre propre code équivalent.

1
Aaron Altman