简体   繁体   English

如何获取全局Windows I / O统计信息?

[英]How to get global Windows I/O statistics?

There is a WinAPI function GetProcessIoCounters that provides details of all I/O operations of a given process: number of read/write operations and number of bytes read/written since the process started. WinAPI函数GetProcessIoCounters提供给定进程的所有I / O操作的详细信息:读取/写入操作的数量以及自进程启动以来读取/写入的字节数。 Most likely Task Manager uses this function to show these numbers: 最有可能的任务管理器使用此函数来显示这些数字:

任务管理器


Is there a relatively easy way to get the same or similar stats, but for the whole system since it started? 是否有一种相对简单的方法来获得相同或相似的统计数据,但是从整个系统开始以来?

Please note, that it is not the same as enumerate all current processes and sum up results of GetProcessIoCounters , because there are processes that start, run for a while and finish. 请注意,它与枚举所有当前进程并总结GetProcessIoCounters结果不同,因为有些进程启动,运行一段时间并完成。 At the time when I call GetProcessIoCounters such processes don't exist anymore, but I would like to know the overall I/O of the system. 当我调用GetProcessIoCounters这样的进程不再存在,但我想知道系统的整体I / O.

I intend to collect these stats every hour or so and log them into the database for future analysis and to help with debugging. 我打算每小时收集一次这些统计数据并将其记录到数据库中以供将来分析并帮助调试。

I'm looking for a method that works on Windows XP without WMI (we use a significantly cut-down Windows XP Embedded), but if such method exists only for later versions of Windows, please share it. 我正在寻找一种适用于没有WMI的Windows XP的方法(我们使用明显缩减的Windows XP Embedded),但如果这种方法仅适用于更高版本的Windows,请分享。 Eventually it will be useful. 最终它会很有用。

Update 更新

I tried the DeviceIoControl(IOCTL_DISK_PERFORMANCE) method suggested by Jerry Coffin . 我尝试了Jerry Coffin建议的DeviceIoControl(IOCTL_DISK_PERFORMANCE)方法。

I had to run diskperf.exe -Y to make it work. 我必须运行diskperf.exe -Y才能使它工作。 I didn't even have to reboot, but without it DeviceIoControl was failing with GetLastError=31 (A device attached to the system is not functioning.) DeviceIoControl continued to work after reboot without the need to run diskperf.exe -Y again, but the first call to DeviceIoControl after reboot returned zeros in all fields (BytesRead, BytesWritten, ReadCount, WriteCount). 我甚至没有重启,但没有它, DeviceIoControl失败, GetLastError=31 (连接到系统的设备无法运行。) DeviceIoControl在重新启动后继续工作而无需再次运行diskperf.exe -Y ,但是重新启动后第一次调用DeviceIoControl在所有字段(BytesRead,BytesWritten,ReadCount,WriteCount)中返回零。 Further calls returned non-zero stats. 进一步的调用返回非零统计数据。 Obviously, there was some substantial disk activity when the system started, but it was not counted. 显然,系统启动时会有一些实质性的磁盘活动,但它没有被计算在内。 So, it looks like that the first call to DeviceIoControl after reboot indeed enables/starts the counters. 因此,看起来重启后第一次调用DeviceIoControl确实启用/启动计数器。

If I run diskperf.exe -N , then DeviceIoControl stops working immediately without the need to reboot. 如果我运行diskperf.exe -N ,则DeviceIoControl立即停止工作而无需重新启动。 When I run diskperf.exe -Y , then DeviceIoControl works fine again. 当我运行diskperf.exe -YDeviceIoControl再次正常工作。

Now the question is: what diskperf.exe -Y does and how to do the same thing in my program? 现在问题是: diskperf.exe -Y做了什么,以及如何在我的程序中做同样的事情?

Update 2 更新2

I exported the whole registry after diskperf.exe -Y and after diskperf.exe -N and looked for the difference. 我在diskperf.exe -Y之后和diskperf.exe -N之后导出整个注册表并查找差异。 The only difference I could find was in one key: 我能找到的唯一区别是一键:

HKEY_LOCAL_MACHINE\SYSTEM\CurrentControlSet\Services\PartMgr
"EnableCounterForIoctl"=dword:00000001

diskperf.exe -Y adds this key, diskperf.exe -N removes it. diskperf.exe -Y添加此密钥, diskperf.exe -N将其删除。

I tried to add/delete this key directly into the registry. 我试图将此密钥直接添加/删除到注册表中。


If the key doesn't exist and DeviceIoControl doesn't work (after I run diskperf.exe -N ) and I add this key like this: 如果该密钥不存在且DeviceIoControl不起作用(在我运行diskperf.exe -N )并且我添加了这样的密钥:

reg add "HKLM\SYSTEM\CurrentControlSet\Services\PartMgr" /v EnableCounterForIoctl /t REG_DWORD /d 1

, then DeviceIoControl begins to work immediately. ,然后DeviceIoControl立即开始工作。

If the key exists and DeviceIoControl works (after I run diskperf.exe -Y ) and I delete this key like this: 如果密钥存在且DeviceIoControl正常工作(在我运行diskperf.exe -Y ),我将删除此密钥,如下所示:

reg delete "HKLM\SYSTEM\CurrentControlSet\Services\PartMgr" /v EnableCounterForIoctl

then DeviceIoControl continues to work and the returned statistics keeps growing. 然后DeviceIoControl继续工作,返回的统计信息不断增长。 Until reboot. 直到重启。

diskperf.exe must be doing something else in addition to changing the registry value, something like forcing the flush/refresh of the registry. 除了更改注册表值之外, diskperf.exe必须执行其他操作,例如强制刷新/刷新注册表。 In my case I care about enabling these counters and it seems to work with the simple adding of the registry key. 在我的情况下,我关心启用这些计数器,它似乎与简单添加注册表项一起使用。

You can get the data one disk at a time using DeviceIoControl, something like this: 您可以使用DeviceIoControl一次获取一个磁盘数据,如下所示:

#include <windows.h>
#include <iostream>

int main() { 
    HANDLE dev = CreateFile("\\\\.\\C:", 
        FILE_READ_ATTRIBUTES, 
        FILE_SHARE_READ | FILE_SHARE_WRITE, 
        NULL, 
        OPEN_EXISTING, 
        0, 
        NULL);

    DISK_PERFORMANCE disk_info { };
    DWORD bytes;

    if (dev == INVALID_HANDLE_VALUE) {
        std::cerr << "Error opening disk\n";
        return 1;
    }

    if (!DeviceIoControl(dev, 
            IOCTL_DISK_PERFORMANCE, 
            NULL, 
            0, 
            &disk_info, 
            sizeof(disk_info), 
            &bytes, 
            NULL))
    {
        std::cerr << "Failure in DeviceIoControl\n";
        return 1;
    }

    std::cout.imbue(std::locale(""));
    std::cout << "Bytes read: " << disk_info.BytesRead.QuadPart << "\n";
    std::cout << "Bytes written: " << disk_info.BytesWritten.QuadPart << "\n";
}

For example, on my machine right now, this shows: 例如,在我的机器上,这显示:

Bytes read: 15,768,173,568
Bytes written: 22,370,663,424

Experimentally, the results I'm getting look reasonable. 实验上,我得到的结果看起来很合理。 For example, after plugging in a flash drive and opening a preview of some pictures on it, I get: 例如,在插入闪存驱动器并打开其中一些图片的预览后,我得到:

Bytes read: 3,956,736
Bytes written: 0

To get the data for all drives currently visible in the system, add a call to GetLogicalDrives or GetLogicalDriveStrings , and call code like this in a loop, but filling in the appropriate drive letter for each call. 要获取系统中当前可见的所有驱动器的数据,请添加对GetLogicalDrivesGetLogicalDriveStrings调用,并在循环中调用此类代码,但为每个调用填写相应的驱动器号。

This still isn't guaranteed to be all the data since the system was booted though. 自从系统启动以来,这仍然不能保证是所有数据。 For example, if you eject a removable disk, information about what was read from/written to that drive is lost. 例如,如果弹出可移动磁盘,则会丢失有关从该驱动器读取/写入内容的信息。 If you plug it back in, you'll only get data about what was read/written since the last time it was plugged in. 如果将其重新插入,则只会获得自上次插入以来读取/写入内容的数据。

I'm not at all sure you're going to be able to do a whole lot better than that though, at least without doing a fair amount of extra work to collect data periodically and keep track of when disks are ejected and inserted and such. 我完全不确定你能做多少比这更好,至少没有做大量的额外工作来定期收集数据并跟踪磁盘弹出和插入的时间等等。 。 When a disk is ejected, I suspect Windows pretty much throws away all the statistics about that drive, so if it's later plugged back in, Windows no longer has stats about what was done with it prior to ejection. 当磁盘弹出时,我怀疑Windows几乎抛弃了有关该驱动器的所有统计信息,因此如果稍后重新插入,Windows将不再关于弹出之前对其执行的操作的统计信息。

Likewise, if a disk has been ejected so it's not currently visible, this won't be able to open it to start with, so it won't be able to retrieve any stats about that drive either. 同样,如果磁盘已被弹出,因此它当前不可见,这将无法打开它,因此它也无法检索有关该驱动器的任何统计信息。

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

相关问题 Windows 操作系统的 I/O 优先级 - I/O Prioritization of Windows OS Windows 系统中是否有无缓冲 I/O? - Is there an un-buffered I/O in Windows system? 仅通过以下方式重定向I / O <iostream> [视窗] - Redirecting I/O only with <iostream> [Windows] 全局C ++ I / O对象是等效的还是使用CI / O流? - Are the global C++ I/O objects equivalent or using the C I/O streams? 如何在Windows GUI应用程序中将嵌入式Python连接到控制台的I / O? - How can I connect embedded Python to the console's I/O in a Windows GUI app? 如何使Unicode iostream i / o在Windows和Unix上都可以工作? - How can I make Unicode iostream i/o work in both Windows and Unix-land? 如何在Windows上使用C ++访问低级硬件I / O功能? - How can I access a low-level hardware I/O functions in C++ on Windows? 如何为 Windows 创建 ELF 格式的 .o 和 .a 文件以用于 C++Builder 10.3.3? - How can I create .o and .a files in ELF format for Windows for the use with C++Builder 10.3.3? 如何捕获I / O异常(确切的I / O,而不是std :: exception) - How to catch I/O exception (exactly I/O, not std::exception) 我想根据两个键排序时如何获得O(log n)? - How do I get a O(log n) when I want to sort according to two keys?
 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM