windows下的底层开发相对Linux比较不方便,这里对主题做一些讨论,和贴一些自己写的代码。
磁盘IO可以由NtQuerySystemInformation获得(2号操作符),这个方法比较轻松,之前的获取CPU使用率也是这样。
但是磁盘的活动时间无法由NtQuerySystemInformation函数查询,因为他并没有提供有关磁盘时间的信息,或者队列情况。(也可能是有,我没有在网上找到资料。)
此外有两种方法获得磁盘详细信息,一种是PDH方法,一种是更底层的DeviceIoControl方法。
第二种方法实现起来比较复杂,不做研究,这里展示PDH方法。
#include
#include
#include
#include
#include
#pragma comment(lib, "pdh.lib")
CONST ULONG SAMPLE_INTERVAL_MS = 1000;
PDH_STATUS Status;
HQUERY Query = NULL;
HCOUNTER Counter;
PDH_FMT_COUNTERVALUE DisplayValue;
DWORD CounterType;
void init()
{
char CounterPathBuffer[] = "\\PhysicalDisk(*)\\% Idle Time";
//
// Create a query.
//
Status = PdhOpenQuery(NULL, NULL, &Query);
if (Status != ERROR_SUCCESS)
{
wprintf(L"\nPdhOpenQuery failed with status 0x%x.", Status);
goto Cleanup;
}
//ZeroMemory(&CounterPathBuffer, sizeof(CounterPathBuffer));
//
// Add the selected counter to the query.
//
Status = PdhAddCounter(Query, CounterPathBuffer, 0, &Counter);
if (Status != ERROR_SUCCESS)
{
wprintf(L"\nPdhAddCounter failed with status 0x%x.", Status);
goto Cleanup;
}
Status = PdhCollectQueryData(Query);
if (Status != ERROR_SUCCESS)
{
wprintf(L"\nPdhCollectQueryData failed with 0x%x.\n", Status);
goto Cleanup;
}
//
// Print counter values until a key is pressed.
//
return;
Cleanup:
if (Query)
{
PdhCloseQuery(Query);
}
}
void wmain(void)
{
init();
while (!_kbhit())
{
Sleep(SAMPLE_INTERVAL_MS);
Status = PdhCollectQueryData(Query);
if (Status != ERROR_SUCCESS)
{
wprintf(L"\nPdhCollectQueryData failed with status 0x%x.", Status);
}
Status = PdhGetFormattedCounterValue(Counter,
PDH_FMT_DOUBLE,
&CounterType,
&DisplayValue);
if (Status != ERROR_SUCCESS)
{
wprintf(L"\nPdhGetFormattedCounterValue failed with status 0x%x.", Status);
goto Cleanup;
}
double DBIOUseTime = DisplayValue.doubleValue;
if (DBIOUseTime > 100) DBIOUseTime = 100;
DBIOUseTime = 100 - DBIOUseTime;
wprintf(L"%0.2f%%\n", DBIOUseTime);
}
Cleanup:
//
// Close the query.
//
if (Query)
{
PdhCloseQuery(Query);
}
}
需要注意的是,PDH方法采集的磁盘活动时间信息,是即时演算的,如果程序本身的活动时间和负载较大,会出现自身干扰。
出现这种情况,可以考虑Sleep 一段时间后再试。
加油。