2011-03-16 45 views
18

Estoy trabajando en un software en el que necesito acceder a los sensores de temperatura en la CPU y obtener el control sobre ellos.¿Cómo acceder a los sensores de calor de la CPU?

No conozco mucha interconexión de hardware; Solo sé cómo interactuar con el mouse. He buscado mucho en Google pero no he podido encontrar ninguna información relevante o fragmento de código.

Realmente necesito agregar esto en mi software. Por favor, guíame sobre cómo controlar los sensores usando C, C++ o ASM.

Respuesta

11

Se puede leer desde el MSAcpi_ThermalZoneTemperature en WMI

mediante WMI de C++ es un poco involucrados, ver MSDN explanantion and examples

nota: se ha cambiado respuesta inútil originales

+0

Software muy relevante, pero el código no está disponible. –

+0

Lo siento, sí, es solo una envoltura alrededor de un dll de propiedad. –

15

Asumo que está interesado en una IA -32 (Arquitectura Intel, 32 bits) CPU y Microsoft Windows.

El Registro específico del modelo (MSR) IA32_THERM_STATUS tiene 7 bits que codifican la "Lectura digital (bits 22:16, RO) - Lectura de temperatura digital en 1 grado Celsius en relación con la temperatura de activación del TCC". (Consulte "14.5.5.2 Lectura del sensor digital" en "Arquitecturas Intel® 64 e IA-32 - Manual del desarrollador de software - Volumen 3 (3A & 3B): Guía de programación del sistema" http://www.intel.com/Assets/PDF/manual/325384.pdf).

Por lo tanto, IA32_THERM_STATUS no le dará la "temperatura de la CPU", pero sí un proxy.

Para leer el registro IA32_THERM_STATUS utiliza la instrucción asm rdmsr, ahora rdmsr no puede ser llamado desde el código de espacio de usuario y por lo que necesita un poco de código espacio del núcleo (tal vez un controlador de dispositivo?).

También puede utilizar el __readmsr intrínseca (ver http://msdn.microsoft.com/en-us/library/y55zyfdx(v=VS.100).aspx) que tiene de todos modos la misma limitación: "Esta función sólo está disponible en modo de núcleo".

Cada núcleo de CPU tiene sus propios sensores térmicos digitales (DTS), por lo que se necesita más código para obtener todas las temperaturas (¿tal vez con la máscara de afinidad? Vea Win32 API SetThreadAffinityMask).

Hice algunas pruebas y de hecho encontré una correlación entre las lecturas DTS IA32_THERM_STATUS y la prueba Prime95 "FFT grandes en el lugar (calor máximo, consumo de energía, algunas pruebas de RAM)". Prime95 es ftp://mersenne.org/gimps/p95v266.zip

No encontré una fórmula para obtener la "temperatura de la CPU" (lo que sea que eso signifique) de la lectura de DTS.

Editar:

citando a un interesante post TJunction Max? #THERMTRIP? #PROCHOT? por "fgw" (diciembre de 2007):

no hay manera de encontrar tjmax de un determinado procesador en ningún registro. por lo tanto, ningún software puede leer este valor. lo que varios desarrolladores de software están haciendo, es que simplemente asumen una cierta función para un determinado procesador y mantienen esta información en una tabla dentro del programa. además de eso, tjmax ni siquiera es el valor correcto que buscan.en hecho que están buscando el umbral de temperatura de activación de TCC. este umbral de temperatura se usa para calcular las temperaturas centrales actuales absolutas de . teórico puede decir: absoluto coretemperature = umbral de temperatura de activación de TCC - DTS tuve que decir teóricamente porque, como se indicó anteriormente, este umbral de temperatura de activación de TCC no puede leerse por software y el programador debe suponer . en la mayoría de las situaciones (coretemp, everest, ...) ellos asumen un valor de 85C o 100C dependiendo de la familia del procesador y la revisión . como este umbral de temperatura de activación de TCC se calibra durante la fabricación individual por procesador, podría ser 83C para un procesador, pero puede ser 87C para el otro. teniendo en cuenta el modo en el que esos programas están calculando las temperaturas centrales, puede averiguar por su cuenta, ¡qué tan exactas son las temperaturas centrales absolutas! ni tjmax ni el umbral de temperatura de activación de TCC "más buscado" se puede encontrar en ningún documento público de información. después de algunas discusiones en el foro de desarrolladores de Intel, Intel no muestra ninguna señal para hacer que esta información esté disponible.

+0

¿Puedo de alguna manera cambiar los valores de la misma? –

+0

@ Akito ¿Quiere decir escribir en el registro 'IA32_THERM_STATUS'? ¿Cuál es el propósito? –

+0

Estoy tratando de investigar sobre las vulnerabilidades de seguridad del hardware, así que estaba pensando en averiguar si de alguna manera podría cambiar la temperatura del valor medida para que la computadora se apague. –

0

Probablemente dependa del sistema operativo. En GNU/Linux, está relacionado con ACPI. Y algunos hardware ni siquiera tienen los dispositivos físicos para medir la temperatura.

+0

Es por eso que he mencionado Windows. –

17

Sin un controlador de kernel específico, es difícil consultar la temperatura, a través de WMI. Aquí es una pieza de código C que lo hace, en base a la clase de WMI MSAcpi_ThermalZoneTemperature:

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

y algo de código de prueba:

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); 
} 
+0

Gracias por la respuesta. –

+0

Es realmente una lástima que casi ningún controlador del sistema implemente esta clase WMI, porque significa que tiene que escribir su propio controlador en modo kernel la mayor parte del tiempo. –

+0

Dos problemas: (1) Por alguna razón, cuando llamo a este método WMI (de un proceso no elevado) 'IEnumWbemClassObject :: Next()' siempre devuelve '80041003'. Y (2) incluso si llamo a este proceso elevado, la llamada WMI tiene éxito pero el valor devuelto nunca cambia, asumiendo que uno lo emite como tal: '((double) temp/10 - 273.15)'. Obtengo '27.85' que es incorrecto. ¿Alguna idea de por qué? – c00000fd

Cuestiones relacionadas