web-dev-qa-db-ja.com

CPU温度を取得する

CPU温度を取得したい。以下は、C++とWMIを使用して行ったことです。私はMSAcpi_ThermalZoneTemperatureを読んでいますが、常に同じで、CPU温度ではありません。

ドライバーを書かずにCPUの実際の温度を取得する方法はありますか?または、使用できるライブラリはありますか?前もって感謝します。

#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

言われるべき真実、それはハードウェアに依存します。

ほとんどのハードウェアで動作するライブラリはOpenHardwareMonitorLibですが、残念ながらドキュメントはなく、実際には独立したソフトウェアとして存在していません。 「Open Hardware Monitor」という名前のオープンソースソフトウェアの一部です。幸いにもDLLを取得でき、GUIは実際のバックエンドであるOpenHardwareMonitorLibから完全に100%分離されています。残念ながら.NET C Sharpで行われ、もちろんWindowsでのみ機能します。読むC++からの使用方法に関するこの投稿

ネイティブC++からC#ライブラリを呼び出す方法(C++\CLIおよびIJWを使用)

したがって、ドキュメントがないことを考えると、これは作業が少し難しい場合があります。しばらくソースを読んだ後、これは私の見解です:

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;

この#Cコードは、CelciusのIntel Haswell CPUの温度を取得するために検証されており、AMDおよびIntelの他のほとんどのCPUで動作する可能性が高いです。 OpenHardwareMonitorLib.dllが必要です。 source からコンパイルできます

このライブラリを使用すると、システムに関する他の多くの情報を取得できます。

ユーザーのCPUは複数の温度センサーを持つことができることに注意してください。たとえば、すべてのコアの温度センサーなので、上の例で行ったように最後のセンサーを常に使用するわけではありません。

幸運を。

2
tomer zeitune

Tomer's answer で提供されているOpenHardwareMonitorLibのソースへのリンクは、さまざまなタイプのCPUからこの情報を読み取るために低レベルで何が行われる必要があるかを示しています。たとえば、 IntelCP クラスは、いくつかのモデル固有のレジスターを定義します。

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;

これらは DTS/PECIによるCPUモニタリング (セクション16「直接MSRアクセス」)のようなIntelのドキュメントから直接抜粋したものです。それらはIntel Software Developer Manualにも記載されているかもしれませんが、私はチェックしていません。

OpenHardwareMonitorLibはRdmsrおよびRdmsrTxを使用して、対象のMSRから温度値を取得します。

対応するAMDコード は、PCIレジスタから同様の情報を取得するように見えます。 AMDはこれを定義する同等のドキュメントをどこかに持っています。

どちらの場合も、これらは定義により、ハードウェアがその温度センサーに関する情報を公開する方法です。このようなライブラリを使用して、内部でこれを実行するか、独自の同等のコードを記述できます。

1
Aaron Altman