2011-03-16 23 views
18

Tôi đang làm việc trên phần mềm mà tôi cần truy cập vào các cảm biến nhiệt độ trong CPU và kiểm soát chúng.Làm cách nào để truy cập bộ cảm biến nhiệt của CPU?

Tôi không biết nhiều giao diện phần cứng; Tôi chỉ biết cách giao tiếp bằng chuột. Tôi đã googled rất nhiều về nó, nhưng không tìm thấy bất kỳ thông tin có liên quan hoặc đoạn mã.

Tôi thực sự cần thêm phần mềm này vào phần mềm của mình. Vui lòng hướng dẫn tôi cách kiểm soát các cảm biến bằng C hoặc C++ hoặc ASM.

Trả lời

11

Bạn có thể đọc nó từ MSAcpi_ThermalZoneTemperature trong WMI

Sử dụng WMI từ C++ là một chút liên quan, thấy MSDN explanantion and examples

lưu ý: Thay đổi gốc câu trả lời vô ích

+0

phần mềm Rất có liên quan nhưng mã không có sẵn. –

+0

Xin lỗi - có nó chỉ là một wrapper xung quanh một số dll proprietry. –

15

tôi giả sử bạn đang quan tâm đến một IA -32 (Intel Architecture, 32-bit) CPU và Microsoft Windows.

Đăng ký mẫu cụ thể (MSR) IA32_THERM_STATUS có 7 bit mã hóa "Readout kỹ thuật số (bits 22:16, RO) - Nhiệt độ kỹ thuật số đọc ở 1 độ C so với nhiệt độ kích hoạt TCC." (xem "14.5.5.2 Đọc Cảm biến Kỹ thuật số" trong "Kiến trúc Intel® 64 và IA-32 - Hướng dẫn của Nhà phát triển Phần mềm - Tập 3 (3A & 3B): Hướng dẫn Lập trình Hệ thống" http://www.intel.com/Assets/PDF/manual/325384.pdf).

Vì vậy, IA32_THERM_STATUS sẽ không cung cấp cho bạn "nhiệt độ CPU" nhưng một số proxy cho nó.

Để đọc IA32_THERM_STATUS đăng ký, bạn sử dụng lệnh asm rdmsr, bây giờ rdmsr không thể được gọi từ mã không gian người dùng và vì vậy bạn cần một số mã không gian hạt nhân (có thể là một thiết bị điều khiển?).

Bạn cũng có thể sử dụng nội tại __readmsr (xem http://msdn.microsoft.com/en-us/library/y55zyfdx(v=VS.100).aspx) có cùng giới hạn: "Chức năng này chỉ khả dụng ở chế độ hạt nhân".

Mỗi lõi CPU có cảm biến nhiệt kỹ thuật số riêng (DTS) và do đó cần thêm một số mã để có được tất cả nhiệt độ (có thể với mặt nạ sở thích? Xem Win32 API SetThreadAffinityMask).

Tôi đã thực hiện một số thử nghiệm và thực sự đã tìm thấy mối tương quan giữa các chỉ số DTS IA32_THERM_STATUS DTS và Prime95 "Kiểm tra FFT lớn nhất (nhiệt độ tối đa, tiêu thụ điện năng, một số RAM được thử nghiệm)". Prime95 là ftp://mersenne.org/gimps/p95v266.zip

Tôi không tìm thấy công thức để nhận "nhiệt độ CPU" (bất kỳ điều gì có thể có nghĩa) từ đọc DTS.

Edit:

Trích dẫn từ một bài thú vị TJunction Max? #THERMTRIP? #PROCHOT? bởi "fgw" (tháng 12 năm 2007):

không có cách nào để tìm TJMax của một bộ xử lý nhất định trong bất kỳ đăng ký. do đó không có phần mềm nào có thể đọc được giá trị này. những gì các nhà phát triển phần mềm khác nhau đang làm, là họ chỉ đơn giản là giả định một tjunction nhất định cho một bộ xử lý nhất định và giữ thông tin này trong một bảng trong chương trình. bên cạnh đó, tjmax không phải là giá trị chính xác của chúng.trong thực tế, họ đang tìm ngưỡng nhiệt độ hoạt động TCC. ngưỡng nhiệt độ này được sử dụng để tính toán coretemperatures tuyệt đối hiện tại từ. lý thuyết bạn có thể nói: tuyệt đối coretemperature = TCC activacion ngưỡng nhiệt độ - DTS tôi đã phải nói về mặt lý thuyết vì, như đã nêu ở trên, TCC activacion ngưỡng nhiệt độ này không thể đọc được bằng phần mềm và phải được giả định bởi lập trình viên. trong hầu hết các trường hợp (coretemp, everest, ...) chúng giả định giá trị 85C hoặc 100C tùy thuộc vào họ bộ vi xử lý và sửa đổi. vì ngưỡng nhiệt độ hoạt hóa TCC này được hiệu chỉnh trong quá trình sản xuất riêng lẻ trên mỗi bộ xử lý, nó có thể là 83C đối với một bộ xử lý nhưng có thể là 87C cho bộ xử lý kia. có tính đến các cách thức những chương trình đó đang tính toán các coretemperatures, bạn có thể tự mình tự mình vẽ số , mức độ coretemperatures tuyệt đối chính xác như thế nào! không phải tjmax cũng như ngưỡng nhiệt độ hoạt động TCC "muốn" nhất có thể được tìm thấy trong bất kỳ tài liệu công khai nào. sau một số cuộc thảo luận trên diễn đàn nhà phát triển intel, intel không hiển thị dấu hiệu nào để cung cấp thông tin này .

+0

Tôi có thể thay đổi giá trị của nó bằng cách nào đó không? –

+0

@Akito Bạn có nghĩa là ghi vào sổ đăng ký 'IA32_THERM_STATUS'? Mục đích là gì? –

+0

Tôi đang cố gắng nghiên cứu về các lỗ hổng bảo mật phần cứng vì vậy tôi đã suy nghĩ để tìm hiểu xem bạn có thể bằng cách nào đó thay đổi nhiệt độ giá trị đo để máy tính có thể bị tắt. –

0

Nó có thể phụ thuộc vào hệ điều hành. Trên GNU/Linux, nó có liên quan đến ACPI. Và một số phần cứng thậm chí không có các thiết bị vật lý để đo nhiệt độ.

+0

Đó là lý do tại sao tôi đã đề cập đến Windows. –

17

Không có trình điều khiển hạt nhân cụ thể, rất khó để truy vấn nhiệt độ, ngoài WMI. Dưới đây là một đoạn mã C nào đó, dựa trên lớp MSAcpi_ThermalZoneTemperature WMI của:

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

và một số mã kiểm tra:

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

Cảm ơn câu trả lời. –

+0

Nó thực sự là một sự xấu hổ mà hầu như không có trình điều khiển hệ thống thực hiện lớp WMI này, bởi vì nó có nghĩa là bạn phải viết trình điều khiển chế độ hạt nhân của riêng bạn cho phần lớn thời gian. –

+0

Hai vấn đề: (1) Vì một lý do nào đó khi tôi gọi phương thức WMI này (từ một quá trình không nâng cao) 'IEnumWbemClassObject :: Next()' luôn trả về '80041003'. Và (2) ngay cả khi tôi gọi quá trình này nâng cao cuộc gọi WMI thành công nhưng giá trị trả về không bao giờ thay đổi, giả sử một kết quả đầu ra như sau: '((double) temp/10 - 273.15)'. Tôi nhận được '27,85' đó là sai. Bất kỳ ý tưởng tại sao? – c00000fd

Các vấn đề liên quan