gpt4 book ai didi

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

转载 作者:可可西里 更新时间:2023-11-01 14:49:19 28 4
gpt4 key购买 nike

有一个 WinAPI 函数 GetProcessIoCounters它提供给定进程的所有 I/O 操作的详细信息:自进程启动以来读/写操作的数量和读/写的字节数。任务管理器很可能使用此功能来显示这些数字:

Task Manager


是否有一种相对简单的方法来获取相同或相似的统计数据,但对于自启动以来的整个系统

请注意,这与枚举所有当前进程并汇总 GetProcessIoCounters 的结果不同,因为存在启动、运行一段时间和结束的进程。当我调用 GetProcessIoCounters 时,这样的进程不再存在,但我想知道系统的整体 I/O。

我打算每隔一小时左右收集一次这些统计数据,并将它们记录到数据库中以供将来分析和帮助调试。

我正在寻找一种在没有 WMI 的 Windows XP 上工作的方法(我们使用显着减少的 Windows XP Embedded),但如果这种方法只适用于更高版本的 Windows,请分享它。最终它会有用。

更新

我尝试了 Jerry Coffin 建议的 DeviceIoControl(IOCTL_DISK_PERFORMANCE) 方法.

我必须运行 diskperf.exe -Y让它工作。我什至不必重新启动,但如果没有它,DeviceIoControl 会失败并显示 GetLastError=31(连接到系统的设备无法正常工作。)DeviceIoControl 在重新启动后继续工作,无需再次运行 diskperf.exe -Y,但在重新启动后第一次调用 DeviceIoControl 在所有字段(BytesRead、 BytesWritten、ReadCount、WriteCount)。进一步的调用返回非零统计数据。显然,系统启动时有一些大量的磁盘事件,但没有计算在内。因此,重启后第一次调用 DeviceIoControl 确实启用/启动了计数器。

如果我运行 diskperf.exe -N,则 DeviceIoControl 会立即停止工作,无需重新启动。当我运行 diskperf.exe -Y 时,DeviceIoControl 再次正常工作。

现在的问题是:diskperf.exe -Y 做了什么以及如何在我的程序中做同样的事情?

更新 2

我在 diskperf.exe -Ydiskperf.exe -N 之后导出了整个注册表并寻找差异。我能找到的唯一区别在于一个键:

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

diskperf.exe -Y 添加此 key ,diskperf.exe -N 删除它。

我尝试直接在注册表中添加/删除此键。


如果 key 不存在并且 DeviceIoControl 不起作用(在我运行 diskperf.exe -N 之后),我将像这样添加此 key :

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

,然后 DeviceIoControl 立即开始工作。

如果 key 存在并且 DeviceIoControl 有效(在我运行 diskperf.exe -Y 之后),我将像这样删除该 key :

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

然后 DeviceIoControl 继续工作并且返回的统计数据不断增长。直到重启。

diskperf.exe 除了更改注册表值外,还必须执行其他操作,例如强制刷新/刷新注册表。在我的例子中,我关心启用这些计数器,它似乎可以通过简单地添加注册表项来工作。

最佳答案

您可以使用 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";
}

例如,现在在我的机器上显示:

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

根据实验,我得到的结果看起来很合理。例如,插入闪存驱动器并打开其中一些图片的预览后,我得到:

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

要获取系统中当前可见的所有驱动器的数据,请添加对 GetLogicalDrivesGetLogicalDriveStrings 的调用,并在循环中调用这样的代码,但填写每次调用的适当驱动器号。

虽然这仍然不能保证是系统启动后的所有数据。例如,如果弹出可移动磁盘,有关从该驱动器读取/写入的内容的信息将丢失。如果将其重新插入,您将只会获得自上次插入后读取/写入的数据。

不过,我完全不确定您是否能够做得比这更好,至少不需要做大量的额外工作来定期收集数据并跟踪磁盘何时弹出和插入等。当磁盘弹出时,我怀疑 Windows 几乎丢弃了关于该驱动器的所有统计信息,因此如果稍后将其重新插入,Windows 将不再关于弹出之前对其执行的操作的统计信息。

同样,如果磁盘已弹出,因此当前不可见,则无法打开它,因此也无法检索有关该驱动器的任何统计信息。

关于c++ - 如何获取全局 Windows I/O 统计信息?,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/30450157/

28 4 0
Copyright 2021 - 2024 cfsdn All Rights Reserved 蜀ICP备2022000587号
广告合作:1813099741@qq.com 6ren.com