web-dev-qa-db-fra.com

Comment accéder aux capteurs de chaleur du processeur?

Je travaille sur un logiciel dans lequel j'ai besoin d'accéder aux capteurs de température de la CPU et de les contrôler.

Je ne connais pas beaucoup d'interface matérielle; Je sais juste comment interfacer avec la souris. J'ai beaucoup cherché à ce sujet dans Google mais je n'ai trouvé aucune information pertinente ni morceau de code.

J'ai vraiment besoin d'ajouter cela dans mon logiciel. Merci de me guider pour avoir le contrôle des capteurs en C ou C++ ou ASM.

20
Fahad Uddin

Sans pilote de noyau spécifique, il est difficile d'interroger la température autrement que via WMI. Voici un extrait de code C basé sur la classe MSAcpi_ThermalZoneTemperature de WMI:

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;
}

et un code de test:

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);
}
17
Simon Mourier

Je suppose que vous êtes intéressé par un processeur IA-32 (architecture Intel, 32 bits) et Microsoft Windows.

Le registre spécifique de modèle (MSR) IA32_THERM_STATUS contient 7 bits codant pour la "Lecture numérique (bits 22:16, RO) - Lecture de la température numérique en degrés Celsius par rapport à la température d'activation TCC". (voir "14.5.5.2 Lecture du capteur numérique" dans "Architectures Intel® 64 et IA-32 - Manuel du développeur logiciel - Volume 3 (3A & 3B): Guide de programmation système" http://www.intel.com/ Assets/PDF/manual/325384.pdf ).

Donc, IA32_THERM_STATUS ne vous donnera pas la "température du processeur" mais un proxy pour cela.

Afin de lire le registre IA32_THERM_STATUS, vous utilisez l'instruction asm rdmsr. Désormais, rdmsr ne peut plus être appelé à partir du code d'espace utilisateur. Vous avez donc besoin d'un code d'espace noyau (peut-être un pilote de périphérique?).

Vous pouvez également utiliser le __readmsr intrinsèque (voir http://msdn.Microsoft.com/en-us/library/y55zyfdx(v=VS.100).aspx ) qui a de toute façon la même limitation: "Cette fonction est uniquement disponible en mode noyau ".

Chaque cœur de processeur a ses propres capteurs thermiques numériques (DTS). Il est donc nécessaire de disposer de davantage de code pour obtenir toutes les températures (peut-être avec le masque d’affinité? Voir Win32 API SetThreadAffinityMask).

J'ai fait quelques tests et trouvé une corrélation entre le test IA32_THERM_STATUS DTS et le test Prime95 "FFT volumineuses sur place (chaleur maximale, consommation électrique, certains RAM testés)". Prime95 est ftp://mersenne.org/gimps/p95v266.Zip

Je n'ai pas trouvé de formule pour obtenir la "température du processeur" (quoi que cela puisse vouloir dire) à partir de la lecture DTS.

Modifier:

Citant un article intéressant TJunction Max? #THERMTRIP? #PROCHOT? Par "fgw" (décembre 2007):

il n’existe aucun moyen de trouver tjmax d’un processeur donné dans aucun registre. Aucun logiciel ne peut donc lire cette valeur. Ce que font différents développeurs de logiciels , c’est qu’ils assument simplement une certaine fonction pour un certain processeur et conservent ces informations dans un tableau du programme. (à part cela, tjmax n’est pas même la valeur correcte, ils sont après. en fait, ils recherchent le seuil de température d’activation TCC. Ce seuil de température est utilisé pour calculer les températures absolues actuelles de à partir de. théorique, vous pouvez dire: absolu température-température = seuil de température d'activation TCC - DTS i devait dire théoriquement parce que, comme indiqué ci-dessus, cette température d'activation TCC Le seuil ne peut pas être lu par un logiciel et doit être supposé par le programmeur. dans la plupart des situations (coretemp, everest, ...), ils prennent une valeur de 85 ° C ou 100 ° C, en fonction de la famille du processeur et de révision. comme ce seuil de température d'activation TCC est calibré lors de la fabrication individuelle par processeur, il pourrait être de 83 ° C pour un processeur mais de 87 ° C pour l'autre. En prenant en compte la manière dont ces programmes calculent les températures, vous pouvez calculer vous-même la précision exacte de la température absolue! ni tjmax ni le seuil de température d'activation TCC "le plus recherché" ne peuvent être trouvés dans aucun document public. à la suite de discussions sur le forum des développeurs Intel, intel ne montre aucun signe pour rendre ces informations disponibles.

15
Alessandro Jacopson

Vous pouvez le lire à partir de MSAcpi_ThermalZoneTemperature dans WMI.

L’utilisation de WMI à partir de C++ est un peu compliquée, voir Explications MSDN et exemples

note: modification de la réponse originale inutile

11
Martin Beckett

Cela dépend probablement du système d'exploitation. Sous GNU/Linux, il est lié à ACPI. Et certains matériels n’ont même pas les dispositifs physiques pour mesurer la température. 

0