C Hardware Info Code Generator

Generated C Code

Code Preview:
Compilation Instructions:

Complete Guide: Lấy Thông Tin Phần Cứng Máy Tính Bằng C

Việc lấy thông tin phần cứng máy tính bằng ngôn ngữ C là một kỹ thuật quan trọng trong lập trình hệ thống. Bài viết này sẽ hướng dẫn chi tiết cách thu thập thông tin về CPU, RAM, ổ đĩa và các thành phần phần cứng khác trên các hệ điều hành phổ biến.

1. Cơ Bản Về Truy Cập Phần Cứng Trong C

Ngôn ngữ C cung cấp khả năng tương tác trực tiếp với phần cứng thông qua:

  • Các hàm hệ thống (system calls)
  • Truy cập trực tiếp vào các file đặc biệt trong hệ thống
  • Sử dụng các thư viện chuyên dụng
#include <stdio.h>
#include <stdlib.h>

int main() {
    // Code lấy thông tin phần cứng sẽ được đặt ở đây
    return 0;
}

2. Lấy Thông Tin CPU

2.1 Trên Hệ Điều Hành Windows

Sử dụng Windows API thông qua thư viện <windows.h>:

#include <windows.h>
#include <stdio.h>

void getCPUInfo() {
    SYSTEM_INFO sysInfo;
    GetSystemInfo(&sysInfo);
    printf(“Number of processors: %d\n”, sysInfo.dwNumberOfProcessors);
    printf(“Processor type: %d\n”, sysInfo.dwProcessorType);
}

2.2 Trên Hệ Điều Hành Linux

Đọc file /proc/cpuinfo:

#include <stdio.h>

void getCPUInfo() {
    FILE *fp = fopen(“/proc/cpuinfo”, “r”);
    if (fp == NULL) {
        perror(“Error opening file”);
        return;
    }
    char buffer[1024];
    while (fgets(buffer, sizeof(buffer), fp) != NULL) {
        printf(“%s”, buffer);
    }
    fclose(fp);
}

3. Lấy Thông Tin RAM

3.1 Phương Pháp Chung

Sử dụng các hàm hệ thống để lấy thông tin bộ nhớ:

#include <stdio.h>
#ifdef _WIN32
#include <windows.h>
#else
#include <sys/sysinfo.h>
#endif

void getRAMInfo() {
#ifdef _WIN32
    MEMORYSTATUSEX memInfo;
    memInfo.dwLength = sizeof(MEMORYSTATUSEX);
    GlobalMemoryStatusEx(&memInfo);
    printf(“Total RAM: %llu MB\n”, memInfo.ullTotalPhys / 1024 / 1024);
#else
    struct sysinfo memInfo;
    sysinfo(&memInfo);
    printf(“Total RAM: %lu MB\n”, memInfo.totalram / 1024 / 1024);
#endif
}

3.2 Thông Tin Chi Tiết Về RAM

Để lấy thông tin chi tiết hơn như loại RAM, tốc độ bus:

  • Trên Windows: Sử dụng WMI (Windows Management Instrumentation)
  • Trên Linux: Đọc file /proc/meminfo
  • Trên macOS: Sử dụng lệnh system_profiler

4. Lấy Thông Tin Ổ Đĩa

4.1 Thông Tin Cơ Bản Về Ổ Đĩa

#include <stdio.h>
#ifdef _WIN32
#include <windows.h>
#else
#include <sys/statvfs.h>
#endif

void getDiskInfo() {
#ifdef _WIN32
    ULARGE_INTEGER freeBytes, totalBytes;
    GetDiskFreeSpaceEx(“C:\\\”, &freeBytes, &totalBytes, NULL);
    printf(“Total disk space: %llu GB\n”, totalBytes.QuadPart / 1024 / 1024 / 1024);
#else
    struct statvfs stat;
    statvfs(“/”, &stat);
    unsigned long blockSize = stat.f_bsize;
    unsigned long totalBlocks = stat.f_blocks;
    printf(“Total disk space: %lu GB\n”, (blockSize * totalBlocks) / 1024 / 1024 / 1024);
#endif
}

4.2 Thông Tin Chi Tiết Về Phân Vùng

Để lấy thông tin chi tiết về các phân vùng đĩa:

#include <stdio.h>
#include <stdlib.h>
#ifdef _WIN32
#include <windows.h>
#endif

void listDrives() {
#ifdef _WIN32
    DWORD drives = GetLogicalDrives();
    for (int i = 0; i < 26; i++) {
        if (drives & (1 << i)) {
            char driveLetter = ‘A’ + i;
            printf(“Drive %c:\\\n”, driveLetter);
        }
    }
#else
    system(“lsblk”); // Linux command to list block devices
#endif
}

5. Lấy Thông Tin GPU

Lấy thông tin card đồ họa đòi hỏi các phương pháp khác nhau trên mỗi hệ điều hành:

5.1 Trên Windows

#include <windows.h>
#include <stdio.h>
#include <dxgi.h>
#include <d3d11.h>
#pragma comment(lib, “dxgi.lib”)
#pragma comment(lib, “d3d11.lib”)

void getGPUInfo() {
    IDXGIFactory *factory = NULL;
    if (FAILED(CreateDXGIFactory(__uuidof(IDXGIFactory), (void**)&factory))) {
        printf(“Failed to create DXGI factory\n”);
        return;
    }

    IDXGIAdapter *adapter = NULL;
    int index = 0;
    while (factory->EnumAdapters(index, &adapter) != DXGI_ERROR_NOT_FOUND) {
        DXGI_ADAPTER_DESC desc;
        adapter->GetDesc(&desc);
        wprintf(L”GPU %d: %s\n”, index + 1, desc.Description);
        printf(” Dedicated Video Memory: %lu MB\n”, (unsigned long)desc.DedicatedVideoMemory / 1024 / 1024);
        adapter->Release();
        index++;
    }
    factory->Release();
}

5.2 Trên Linux

Sử dụng lệnh lspci hoặc đọc file /proc:

#include <stdio.h>

void getGPUInfo() {
    FILE *fp = popen(“lspci | grep -i vga”, “r”);
    if (fp == NULL) {
        perror(“Failed to run command”);
        return;
    }
    char buffer[1024];
    while (fgets(buffer, sizeof(buffer), fp) != NULL) {
        printf(“GPU: %s”, buffer);
    }
    pclose(fp);
}

6. Code Hoàn Chỉnh Lấy Toàn Bộ Thông Tin Phần Cứng

Dưới đây là ví dụ code hoàn chỉnh lấy tất cả thông tin phần cứng trên Linux:

#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <sys/sysinfo.h>
#include <sys/utsname.h>

void getSystemInfo() {
    struct utsname unameData;
    uname(&unameData);
    printf(“System Information:\n”);
    printf(” System Name: %s\n”, unameData.sysname);
    printf(” Node Name: %s\n”, unameData.nodename);
    printf(” Release: %s\n”, unameData.release);
    printf(” Version: %s\n”, unameData.version);
    printf(” Machine: %s\n”, unameData.machine);
}

void getCPUInfo() {
    printf(“\nCPU Information:\n”);
    FILE *fp = fopen(“/proc/cpuinfo”, “r”);
    if (fp == NULL) {
        perror(“Error opening /proc/cpuinfo”);
        return;
    }
    char buffer[1024];
    int processorCount = 0;
    while (fgets(buffer, sizeof(buffer), fp) != NULL) {
        if (strstr(buffer, “processor”) != NULL) {
            processorCount++;
        }
        if (strstr(buffer, “model name”) != NULL ||
            strstr(buffer, “cpu MHz”) != NULL ||
            strstr(buffer, “cache size”) != NULL) {
            printf(” %s”, buffer);
        }
    }
    printf(” Number of processors: %d\n”, processorCount);
    fclose(fp);
}

void getRAMInfo() {
    printf(“\nRAM Information:\n”);
    FILE *fp = fopen(“/proc/meminfo”, “r”);
    if (fp == NULL) {
        perror(“Error opening /proc/meminfo”);
        return;
    }
    char buffer[1024];
    while (fgets(buffer, sizeof(buffer), fp) != NULL) {
        if (strstr(buffer, “MemTotal”) != NULL ||
            strstr(buffer, “MemFree”) != NULL ||
            strstr(buffer, “Buffers”) != NULL ||
            strstr(buffer, “Cached”) != NULL) {
            printf(” %s”, buffer);
        }
    }
    fclose(fp);
}

void getDiskInfo() {
    printf(“\nDisk Information:\n”);
    FILE *fp = popen(“lsblk -o NAME,SIZE,TYPE,MOUNTPOINT”, “r”);
    if (fp == NULL) {
        perror(“Failed to run lsblk command”);
        return;
    }
    char buffer[1024];
    while (fgets(buffer, sizeof(buffer), fp) != NULL) {
        printf(” %s”, buffer);
    }
    pclose(fp);
}

int main() {
    getSystemInfo();
    getCPUInfo();
    getRAMInfo();
    getDiskInfo();
    return 0;
}

7. So Sánh Các Phương Pháp Lấy Thông Tin Phần Cứng

Phương Pháp Windows Linux macOS Độ Phức Tạp Thông Tin Chi Tiết
System Calls ✓ (Windows API) ✓ (syscalls) ✓ (IOKit) Trung bình Cao
Đọc file hệ thống ✓ (/proc, /sys) ✓ (system_profiler) Thấp Trung bình
Thư viện bên thứ 3 Cao Rất cao
Lệnh hệ thống ✓ (wmic, systeminfo) ✓ (lshw, lscpu) ✓ (system_profiler) Thấp Trung bình

8. Thư Viện Hữu Ích Cho Việc Lấy Thông Tin Phần Cứng

Thư Viện Nền Tảng Ngôn Ngữ Tính Năng Chính Link
libcpuid Cross-platform C/C++ Lấy thông tin CPU chi tiết GitHub
Open Hardware Monitor Windows C# Monitor toàn diện phần cứng Website
libstatgrab Linux/Unix C Lấy thống kê hệ thống Website
WMI (Windows Management Instrumentation) Windows C++/C# Truy cập toàn diện thông tin hệ thống Microsoft Docs

9. Các Lưu Ý Khi Lấy Thông Tin Phần Cứng

  1. Quyền truy cập: Nhiều thông tin phần cứng đòi hỏi quyền admin/root để truy cập
  2. Tính cross-platform: Code viết cho Windows thường không chạy được trên Linux và ngược lại
  3. Hiệu suất: Tránh lấy thông tin phần cứng quá thường xuyên trong các ứng dụng thời gian thực
  4. Bảo mật: Không lưu trữ hoặc truyền tải thông tin phần cứng nhạy cảm
  5. Tính tương thích: Kiểm tra trên nhiều phiên bản hệ điều hành khác nhau

10. Tài Nguyên Hữu Ích

Các tài nguyên chính thức và uy tín để tìm hiểu thêm:

11. Ví Dụ Nâng Cao: Lấy Thông Tin Nhiệt Độ CPU

Lấy thông tin nhiệt độ CPU đòi hỏi các phương pháp đặc biệt trên từng hệ điều hành:

11.1 Trên Linux

#include <stdio.h>
#include <stdlib.h>
#include <dirent.h>
#include <string.h>

void getCPUTemperature() {
    DIR *dir;
    struct dirent *entry;
    char path[1024];
    FILE *fp;
    char buffer[1024];
    int found = 0;

    dir = opendir(“/sys/class/thermal/”);
    if (dir == NULL) {
        perror(“Error opening thermal directory”);
        return;
    }

    while ((entry = readdir(dir)) != NULL) {
        if (strstr(entry->d_name, “thermal_zone”) != NULL) {
            snprintf(path, sizeof(path), “/sys/class/thermal/%s/temp”, entry->d_name);
            fp = fopen(path, “r”);
            if (fp != NULL) {
                if (fgets(buffer, sizeof(buffer), fp) != NULL) {
                    int temp = atoi(buffer) / 1000;
                    printf(“CPU Temperature: %d°C\n”, temp);
                    found = 1;
                }
                fclose(fp);
            }
        }
    }
    closedir(dir);

    if (!found) {
        printf(“Could not read CPU temperature\n”);
    }
}

11.2 Trên Windows

Trên Windows, bạn cần sử dụng WMI hoặc các thư viện bên thứ 3 như Open Hardware Monitor:

#define _WIN32_DCOM
#include <windows.h>
#include <comdef.h>
#include <Wbemidl.h>
#pragma comment(lib, “wbemuuid.lib”)

void getCPUTemperature() {
    HRESULT hres;

    // Initialize COM
    hres = CoInitializeEx(0, COINIT_MULTITHREADED);
    if (FAILED(hres)) {
        printf(“Failed to initialize COM library. Error code = 0x%x\n”, hres);
        return;
    }

    // Initialize security
    hres = CoInitializeSecurity(
        NULL,
        -1,
        NULL,
        NULL,
        RPC_C_AUTHN_LEVEL_DEFAULT,
        RPC_C_IMP_LEVEL_IMPERSONATE,
        NULL,
        EOAC_NONE,
        NULL
    );

    if (FAILED(hres)) {
        printf(“Failed to initialize security. Error code = 0x%x\n”, hres);
        CoUninitialize();
        return;
    }

    // Create WMI locator
    IWbemLocator *pLoc = NULL;
    hres = CoCreateInstance(
        CLSID_WbemLocator,
        0,
        CLSCTX_INPROC_SERVER,
        IID_IWbemLocator, (LPVOID *)&pLoc);

    if (FAILED(hres)) {
        printf(“Failed to create IWbemLocator object. Error code = 0x%x\n”, hres);
        CoUninitialize();
        return;
    }

    // Connect to WMI
    IWbemServices *pSvc = NULL;
    hres = pLoc->ConnectServer(
        _bstr_t(L”ROOT\\CIMV2″),
        NULL,
        NULL,
        0,
        NULL,
        0,
        0,
        &pSvc
    );

    if (FAILED(hres)) {
        printf(“Could not connect to WMI. Error code = 0x%x\n”, hres);
        pLoc->Release();
        CoUninitialize();
        return;
    }

    // Set security levels
    hres = CoSetProxyBlanket(
        pSvc,
        RPC_C_AUTHN_WINNT,
        RPC_C_AUTHZ_NONE,
        NULL,
        RPC_C_AUTHN_LEVEL_CALL,
        RPC_C_IMP_LEVEL_IMPERSONATE,
        NULL,
        EOAC_NONE
    );

    if (FAILED(hres)) {
        printf(“Could not set proxy blanket. Error code = 0x%x\n”, hres);
        pSvc->Release();
        pLoc->Release();
        CoUninitialize();
        return;
    }

    // Execute query
    IEnumWbemClassObject* pEnumerator = NULL;
    hres = pSvc->ExecQuery(
        bstr_t(“WQL”),
        bstr_t(“SELECT * FROM MSAcpi_ThermalZoneTemperature”),
        WBEM_FLAG_FORWARD_ONLY | WBEM_FLAG_RETURN_IMMEDIATELY,
        NULL,
        &pEnumerator);

    if (FAILED(hres)) {
        printf(“Query for temperature failed. Error code = 0x%x\n”, hres);
        pSvc->Release();
        pLoc->Release();
        CoUninitialize();
        return;
    }

    // Get data from query
    IWbemClassObject *pclsObj = NULL;
    ULONG uReturn = 0;
    int tempFound = 0;

    while (pEnumerator) {
        HRESULT hr = pEnumerator->Next(WBEM_INFINITE, 1, &pclsObj, &uReturn);
        if (uReturn == 0) break;

        VARIANT vtProp;
        hr = pclsObj->Get(L”CurrentTemperature”, 0, &vtProp, 0, 0);
        if (SUCCEEDED(hr)) {
            int temp = (vtProp.intVal / 10) – 273; // Convert from deci-Kelvin to Celsius
            printf(“CPU Temperature: %d°C\n”, temp);
            tempFound = 1;
        }
        VariantClear(&vtProp);
        pclsObj->Release();
    }

    if (!tempFound) {
        printf(“Could not read CPU temperature\n”);
    }

    // Cleanup
    pSvc->Release();
    pLoc->Release();
    pEnumerator->Release();
    CoUninitialize();
}

12. Kết Luận

Việc lấy thông tin phần cứng bằng ngôn ngữ C đòi hỏi hiểu biết sâu về hệ điều hành và các API hệ thống. Mỗi hệ điều hành có cách tiếp cận riêng:

  • Windows: Sử dụng Windows API và WMI
  • Linux: Đọc các file trong /proc và /sys
  • macOS: Sử dụng IOKit framework

Để phát triển các ứng dụng cross-platform, bạn nên cân nhắc:

  1. Sử dụng các thư viện bên thứ 3 như libcpuid
  2. Triển khai code riêng cho từng nền tảng với các macro điều kiện
  3. Tạo một lớp trừu tượng (abstraction layer) để ẩn đi sự khác biệt giữa các nền tảng

Với kiến thức từ bài viết này, bạn đã có thể bắt đầu phát triển các ứng dụng giám sát phần cứng chuyên nghiệp bằng ngôn ngữ C.

Leave a Reply

Your email address will not be published. Required fields are marked *