有一个 WinAPI 函数 GetProcessIoCounters它提供给定进程的所有 I/O 操作的详细信息:自进程启动以来读/写操作的数量和读/写的字节数。任务管理器很可能使用此功能来显示这些数字:
是否有一种相对简单的方法来获取相同或相似的统计数据,但对于自启动以来的整个系统?
请注意,这与枚举所有当前进程并汇总 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 -Y 和 diskperf.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
要获取系统中当前可见的所有驱动器的数据,请添加对 GetLogicalDrives 或 GetLogicalDriveStrings 的调用,并在循环中调用这样的代码,但填写每次调用的适当驱动器号。
虽然这仍然不能保证是系统启动后的所有数据。例如,如果弹出可移动磁盘,有关从该驱动器读取/写入的内容的信息将丢失。如果将其重新插入,您将只会获得自上次插入后读取/写入的数据。
不过,我完全不确定您是否能够做得比这更好,至少不需要做大量的额外工作来定期收集数据并跟踪磁盘何时弹出和插入等。当磁盘弹出时,我怀疑 Windows 几乎丢弃了关于该驱动器的所有统计信息,因此如果稍后将其重新插入,Windows 将不再关于弹出之前对其执行的操作的统计信息。
同样,如果磁盘已弹出,因此当前不可见,则无法打开它,因此也无法检索有关该驱动器的任何统计信息。
关于c++ - 如何获取全局 Windows I/O 统计信息?,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/30450157/
我正在学习如何使用Nokogiri,根据这段代码我遇到了一些问题:require'rubygems'require'mechanize'post_agent=WWW::Mechanize.newpost_page=post_agent.get('http://www.vbulletin.org/forum/showthread.php?t=230708')puts"\nabsolutepathwithtbodygivesnil"putspost_page.parser.xpath('/html/body/div/div/div/div/div/table/tbody/tr/td/div
总的来说,我对ruby还比较陌生,我正在为我正在创建的对象编写一些rspec测试用例。许多测试用例都非常基础,我只是想确保正确填充和返回值。我想知道是否有办法使用循环结构来执行此操作。不必为我要测试的每个方法都设置一个assertEquals。例如:describeitem,"TestingtheItem"doit"willhaveanullvaluetostart"doitem=Item.new#HereIcoulddotheitem.name.shouldbe_nil#thenIcoulddoitem.category.shouldbe_nilendend但我想要一些方法来使用
关闭。这个问题是opinion-based.它目前不接受答案。想要改进这个问题?更新问题,以便editingthispost可以用事实和引用来回答它.关闭4年前。Improvethisquestion我想在固定时间创建一系列低音和高音调的哔哔声。例如:在150毫秒时发出高音调的蜂鸣声在151毫秒时发出低音调的蜂鸣声200毫秒时发出低音调的蜂鸣声250毫秒的高音调蜂鸣声有没有办法在Ruby或Python中做到这一点?我真的不在乎输出编码是什么(.wav、.mp3、.ogg等等),但我确实想创建一个输出文件。
给定这段代码defcreate@upgrades=User.update_all(["role=?","upgraded"],:id=>params[:upgrade])redirect_toadmin_upgrades_path,:notice=>"Successfullyupgradeduser."end我如何在该操作中实际验证它们是否已保存或未重定向到适当的页面和消息? 最佳答案 在Rails3中,update_all不返回任何有意义的信息,除了已更新的记录数(这可能取决于您的DBMS是否返回该信息)。http://ar.ru
我在我的项目目录中完成了compasscreate.和compassinitrails。几个问题:我已将我的.sass文件放在public/stylesheets中。这是放置它们的正确位置吗?当我运行compasswatch时,它不会自动编译这些.sass文件。我必须手动指定文件:compasswatchpublic/stylesheets/myfile.sass等。如何让它自动运行?文件ie.css、print.css和screen.css已放在stylesheets/compiled。如何在编译后不让它们重新出现的情况下删除它们?我自己编译的.sass文件编译成compiled/t
大约一年前,我决定确保每个包含非唯一文本的Flash通知都将从模块中的方法中获取文本。我这样做的最初原因是为了避免一遍又一遍地输入相同的字符串。如果我想更改措辞,我可以在一个地方轻松完成,而且一遍又一遍地重复同一件事而出现拼写错误的可能性也会降低。我最终得到的是这样的:moduleMessagesdefformat_error_messages(errors)errors.map{|attribute,message|"Error:#{attribute.to_s.titleize}#{message}."}enddeferror_message_could_not_find(obje
我正在寻找执行以下操作的正确语法(在Perl、Shell或Ruby中):#variabletoaccessthedatalinesappendedasafileEND_OF_SCRIPT_MARKERrawdatastartshereanditcontinues. 最佳答案 Perl用__DATA__做这个:#!/usr/bin/perlusestrict;usewarnings;while(){print;}__DATA__Texttoprintgoeshere 关于ruby-如何将脚
我主要使用Ruby来执行此操作,但到目前为止我的攻击计划如下:使用gemsrdf、rdf-rdfa和rdf-microdata或mida来解析给定任何URI的数据。我认为最好映射到像schema.org这样的统一模式,例如使用这个yaml文件,它试图描述数据词汇表和opengraph到schema.org之间的转换:#SchemaXtoschema.orgconversion#data-vocabularyDV:name:namestreet-address:streetAddressregion:addressRegionlocality:addressLocalityphoto:i
Rackup通过Rack的默认处理程序成功运行任何Rack应用程序。例如:classRackAppdefcall(environment)['200',{'Content-Type'=>'text/html'},["Helloworld"]]endendrunRackApp.new但是当最后一行更改为使用Rack的内置CGI处理程序时,rackup给出“NoMethodErrorat/undefinedmethod`call'fornil:NilClass”:Rack::Handler::CGI.runRackApp.newRack的其他内置处理程序也提出了同样的反对意见。例如Rack
在选择我想要运行操作的频率时,唯一的选项是“每天”、“每小时”和“每10分钟”。谢谢!我想为我的Rails3.1应用程序运行调度程序。 最佳答案 这不是一个优雅的解决方案,但您可以安排它每天运行,并在实际开始工作之前检查日期是否为当月的第一天。 关于ruby-如何每月在Heroku运行一次Scheduler插件?,我们在StackOverflow上找到一个类似的问题: https://stackoverflow.com/questions/8692687/