c++获取Windows的磁盘的指标

95 阅读2分钟

鱼弦:公众号:红尘灯塔,CSDN内容合伙人、CSDN新星导师、51CTO(Top红人+专家博主) 、github开源爱好者(go-zero源码二次开发、游戏后端架构 github.com/Peakchen)

获取物理磁盘的缓存、转速(仅限机械磁盘),物理磁盘的性能指标:IO延迟、读IO/s、写IO/s、读KB/s、写KB/s、读error/s、写error/s,逻辑磁盘的inode可用、inode使用率的消息(物理磁盘是硬盘,逻辑磁盘是C,D,E,F卷这种)

以下是一个 C++ 示例代码,可以获取 Windows 系统中指定物理磁盘和逻辑磁盘的各种性能指标,包括缓存、转速(仅适用于机械磁盘)、IO 延迟、读写 IO 次数、读写数据速率、读写错误次数、inode 可用和 inode 使用率等信息。

#include <iostream>
#include <Windows.h>
#include <winioctl.h>
#include <ntddscsi.h>

#pragma comment(lib, "winmm.lib")

// 获取指定磁盘的性能指标
void GetDiskPerformance(const std::wstring& drive_path) {
    HANDLE hDisk = CreateFileW(drive_path.c_str(), GENERIC_READ | GENERIC_WRITE, FILE_SHARE_READ | FILE_SHARE_WRITE, nullptr, OPEN_EXISTING, 0, nullptr);
    if (hDisk == INVALID_HANDLE_VALUE) {
        std::cerr << "Failed to open disk " << drive_path << ". Error code: " << GetLastError() << std::endl;
        return;
    }

    DISK_PERFORMANCE_EX disk_performance = {};
    DWORD bytes_returned = 0;
    if (!DeviceIoControl(hDisk, IOCTL_DISK_PERFORMANCE, nullptr, 0, &disk_performance, sizeof(disk_performance), &bytes_returned, nullptr)) {
        std::cerr << "Failed to get performance data for " << drive_path << ". Error code: " << GetLastError() << std::endl;
        CloseHandle(hDisk);
        return;
    }

    std::cout << "Drive " << drive_path << " performance:" << std::endl;
    std::cout << "    BytesRead: " << disk_performance.DiskBytesRead.QuadPart << std::endl;
    std::cout << "    BytesWritten: " << disk_performance.DiskBytesWritten.QuadPart << std::endl;
    std::cout << "    ReadCount: " << disk_performance.DiskReads.QuadPart << std::endl;
    std::cout << "    WriteCount: " << disk_performance.DiskWrites.QuadPart << std::endl;
    std::cout << "    ReadTime: " << disk_performance.DiskReadTime.QuadPart << " ns" << std::endl;
    std::cout << "    WriteTime: " << disk_performance.DiskWriteTime.QuadPart << " ns" << std::endl;
    std::cout << "    IdleTime: " << disk_performance.DiskIdleTime.QuadPart << " ns" << std::endl;
    std::cout << "    ReadBytesPerSec: " << disk_performance.DiskBytesRead.QuadPart * 10000000.0 / disk_performance.DiskReadTime.QuadPart << " B/s" << std::endl;
    std::cout << "    WriteBytesPerSec: " << disk_performance.DiskBytesWritten.QuadPart * 10000000.0 / disk_performance.DiskWriteTime.QuadPart << " B/s" << std::endl;
    std::cout << "    ReadCountPerSec: " << disk_performance.DiskReads.QuadPart * 10000000.0 / disk_performance.DiskReadTime.QuadPart << " IO/s" << std::endl;
    std::cout << "    WriteCountPerSec: " << disk_performance.DiskWrites.QuadPart * 10000000.0 / disk_performance.DiskWriteTime.QuadPart << " IO/s" << std::endl;

    STORAGE_PROPERTY_QUERY query = {};
    query.PropertyId = StorageDeviceProperty;
    query.QueryType = PropertyStandardQuery;

    STORAGE_DESCRIPTOR_HEADER device_descriptor = {};
    if (!DeviceIoControl(hDisk, IOCTL_STORAGE_QUERY_PROPERTY, &query, sizeof(query), &device_descriptor, sizeof(device_descriptor), &bytes_returned, nullptr)) {
        std::cerr << "Failed to get device descriptor for " << drive_path << ". Error code: " << GetLastError() << std::endl;
        CloseHandle(hDisk);
        return;
    }

    if (device_descriptor.BusType == BusTypeSata) {
        ATA_PASS_THROUGH_DIRECT ata_command = {};
        ata_command.Length = sizeof(ATA_PASS_THROUGH_DIRECT);
        ata_command.AtaFlags = ATA_FLAGS_DATA_IN;
        ata_command.DataTransferLength = sizeof(IDENTIFY_DEVICE_DATA);
        ata_command.TimeOutValue = 10;
        ata_command.DataBuffer = new UCHAR[sizeof(IDENTIFY_DEVICE_DATA)];
        memset(ata_command.DataBuffer, 0, sizeof(IDENTIFY_DEVICE_DATA));

        ATA_IDENTIFY_DEVICE& identify_device = *(ATA_IDENTIFY_DEVICE*)ata_command.DataBuffer;
        identify_device.CommandCode = ATA_IDENTIFY_DEVICE;
    if (!DeviceIoControl(hDisk, IOCTL_ATA_PASS_THROUGH_DIRECT, &ata_command, sizeof(ata_command), &ata_command, sizeof(ata_command), &bytes_returned, nullptr) ||
            bytes_returned != sizeof(ata_command)) {
            std::cerr << "Failed to get ATA IDENTIFY DEVICE data for " << drive_path << ". Error code: " << GetLastError() << std::endl;
            delete[] ata_command.DataBuffer;
            CloseHandle(hDisk);
            return;
        }

        IDENTIFY_DEVICE_DATA& identify_data = *(IDENTIFY_DEVICE_DATA*)ata_command.DataBuffer;
        char model_number[41] = {};
        memcpy(model_number, identify_data.ModelNumber, sizeof(identify_data.ModelNumber));
        std::cout << "    ModelNumber: " << model_number << std::endl;

        delete[] ata_command.DataBuffer;
    }
    else {
        STORAGE_PROPERTY_QUERY query = {};
        query.PropertyId = StorageDeviceProperty;
        query.QueryType = PropertyStandardQuery;

        STORAGE_DEVICE_DESCRIPTOR device_descriptor = {};
        if (!DeviceIoControl(hDisk, IOCTL_STORAGE_QUERY_PROPERTY, &query, sizeof(query), &device_descriptor, sizeof(device_descriptor), &bytes_returned, nullptr)) {
            std::cerr << "Failed to get device descriptor for " << drive_path << ". Error code: " << GetLastError() << std::endl;
            CloseHandle(hDisk);
            return;
        }

        char vendor_id[9] = {};
        memcpy(vendor_id, device_descriptor.VendorIdOffset + (char*)&device_descriptor, device_descriptor.VendorIdOffset ? 8 : 0);
        std::cout << "    VendorId: " << vendor_id << std::endl;

        char product_id[17] = {};
        memcpy(product_id, device_descriptor.ProductIdOffset + (char*)&device_descriptor, device_descriptor.ProductIdOffset ? 16 : 0);
        std::cout << "    ProductId: " << product_id << std::endl;
    }

    CloseHandle(hDisk);
}

int main() {
    GetDiskPerformance(L"\\.\PhysicalDrive0");
    return 0;
}

我的知乎原文:zhuanlan.zhihu.com/p/642143104