Как получить доступ к датчикам тепла процессора? - PullRequest
20 голосов
/ 16 марта 2011

Я работаю над программным обеспечением, в котором мне нужно получить доступ к датчикам температуры в процессоре и получить контроль над ними.

Я не знаю много аппаратных интерфейсов; Я просто знаю, как взаимодействовать с мышью. Я много гуглил по этому поводу, но не смог найти никакой соответствующей информации или фрагмента кода.

Мне действительно нужно добавить это в мою программу. Пожалуйста, объясните мне, как управлять датчиками с помощью C или C ++ или ASM.

Ответы [ 4 ]

17 голосов
/ 27 октября 2011

Без специального драйвера ядра сложно запрашивать температуру, кроме как через WMI. Вот фрагмент кода C, который делает это на основе класса MSIcpi_ThermalZoneTempera от 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;
}

и некоторый тестовый код:

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);
}
15 голосов
/ 24 июля 2011

Я предполагаю, что вы заинтересованы в процессоре IA-32 (архитектура Intel, 32-разрядная версия) и Microsoft Windows.

Регистр для конкретной модели (MSR) IA32_THERM_STATUS имеет 7 бит, кодирующих «Цифровое считывание».(биты 22:16, RO) - Цифровое считывание температуры в 1 градус Цельсия относительно температуры активации TCC. "(см. «14.5.5.2 Чтение цифрового датчика» в «Архитектура Intel® 64 и IA-32 - Руководство разработчика программного обеспечения - Том 3 (3A и 3B): Руководство по системному программированию» http://www.intel.com/Assets/PDF/manual/325384.pdf).

Итак IA32_THERM_STATUS не даст вам "температуру процессора", но для нее будет прокси.

Чтобы прочитать регистр IA32_THERM_STATUS, вы используете инструкцию asm rdmsr, теперь rdmsr нельзя вызвать из пространства пользователякод, и поэтому вам нужен некоторый код пространства ядра (может быть, драйвер устройства?).

Вы также можете использовать встроенный __readmsr (см. http://msdn.microsoft.com/en-us/library/y55zyfdx(v=VS.100).aspx), который в любом случае имеет такое же ограничение: «Эта функциядоступно только в режиме ядра ".

Каждое ядро ​​ЦП имеет свои собственные цифровые термодатчики (DTS), поэтому для получения всех температур требуется еще немного кода (возможно, с маской сродства? см. Win32 API * 1020).*).

Я провел несколько тестов и обнаружил корреляцию между показаниями IA32_THERM_STATUS DTS и тестом Prime95 «Большие FFT на месте (максимальное нагревание, энергопотребление, некоторое количество протестированной оперативной памяти)». FTP: //mersenne.org/gimps/p95v266.zip

Я не нашел формулы для получения "температуры процессора" (что бы это ни значило) из показаний DTS.

Редактировать:

Цитата из интересного поста TJunction Max?#THERMTRIP?#PROCHOT? от "fgw" (декабрь 2007 г.):

нет способа найти tjmax определенного процессора в любом регистре.таким образом, никакое программное обеспечение не может прочитать это значение.что делают разные разработчики программного обеспечения, они просто принимают определенное соединение для определенного процессора и хранят эту информацию в таблице в программе.кроме того, tjmax даже не является правильным значением, за которым они следуют.на самом деле они ищут температурный порог активации TCC.этот температурный порог используется для расчета текущих абсолютных температур ядра.теоретически вы можете сказать: абсолютная температура ядра = порог температуры активации TCC - DTS Я должен был сказать теоретически, потому что, как указано выше, этот порог температуры активации TCC не может быть считан программным обеспечением и должен приниматься программистом.в большинстве ситуаций (coretemp, everest, ...) они принимают значение 85C или 100C в зависимости от семейства процессоров и версии.так как этот порог температуры активации TCC калибруется во время производства индивидуально для каждого процессора, он может составлять 83 ° C для одного процессора, но может быть 87 ° C для другого.Принимая во внимание то, как эти программы вычисляют температуры ядра, вы можете самостоятельно определить, насколько точны абсолютные температуры ядра!Ни tjmax, ни «наиболее требуемый» температурный порог активации TCC не могут быть найдены ни в одной общедоступной информационной документации.после некоторых обсуждений на форуме разработчиков Intel, Intel не показывает никаких признаков, чтобы сделать эту информацию доступной.

11 голосов
/ 16 марта 2011

Вы можете прочитать его из MSAcpi_ThermalZoneTemperat в WMI

Использование WMI из C ++ немного сложное, см. Объяснение MSDN и примеры

примечание: изменен исходный бесполезный ответ

0 голосов
/ 24 октября 2011

Вероятно, это зависит от операционной системы. В GNU / Linux это связано с ACPI. А на некоторых устройствах даже нет физических устройств для измерения температуры.

...