ディスクの特定の読み取り/書き込み速度を取得するにはどうすればよいですか? (アクティビティモニターで確認できるように、1 秒あたりの書き込みデータと 1 秒あたりの読み取りデータ)
注: OS X での Objective-C/C ソリューションを具体的に求めています。
ディスクの特定の読み取り/書き込み速度を取得するにはどうすればよいですか? (アクティビティモニターで確認できるように、1 秒あたりの書き込みデータと 1 秒あたりの読み取りデータ)
注: OS X での Objective-C/C ソリューションを具体的に求めています。
OSX のアクティビティ モニターである XRG をご覧ください。ディスク全体の統計グラバーはXRGDiskView.m
、getDISKcounters
関数内にあります。
要約すると、次のコードを使用してハードドライブのリストを取得します。
#import <IOKit/IOKitLib.h>
#import <IOKit/storage/IOBlockStorageDriver.h>
io_iterator_t drivelist = IO_OBJECT_NULL;
mach_port_t masterPort = IO_OBJECT_NULL;
/* get ports and services for drive stats */
/* Obtain the I/O Kit communication handle */
IOMasterPort(bootstrap_port, &masterPort);
/* Obtain the list of all drive objects */
IOServiceGetMatchingServices(masterPort,
IOServiceMatching("IOBlockStorageDriver"),
&drivelist);
次に、次の関数を呼び出して、システムの起動からディスク上の合計読み取り/書き込みバイト数を取得します。
void getDISKcounters(io_iterator_t drivelist, io_stats *i_dsk, io_stats *o_dsk)
{
io_registry_entry_t drive = 0; /* needs release */
UInt64 totalReadBytes = 0;
UInt64 totalWriteBytes = 0;
while ((drive = IOIteratorNext(drivelist))) {
CFNumberRef number = 0; /* don't release */
CFDictionaryRef properties = 0; /* needs release */
CFDictionaryRef statistics = 0; /* don't release */
UInt64 value = 0;
/* Obtain the properties for this drive object */
IORegistryEntryCreateCFProperties(drive, (CFMutableDictionaryRef *) &properties, kCFAllocatorDefault, kNilOptions);
/* Obtain the statistics from the drive properties */
statistics = (CFDictionaryRef) CFDictionaryGetValue(properties, CFSTR(kIOBlockStorageDriverStatisticsKey));
if (statistics) {
/* Obtain the number of bytes read from the drive statistics */
number = (CFNumberRef) CFDictionaryGetValue(statistics, CFSTR(kIOBlockStorageDriverStatisticsBytesReadKey));
if (number) {
CFNumberGetValue(number, kCFNumberSInt64Type, &value);
totalReadBytes += value;
}
/* Obtain the number of bytes written from the drive statistics */
number = (CFNumberRef) CFDictionaryGetValue (statistics, CFSTR(kIOBlockStorageDriverStatisticsBytesWrittenKey));
if (number) {
CFNumberGetValue(number, kCFNumberSInt64Type, &value);
totalWriteBytes += value;
}
}
/* Release resources */
CFRelease(properties); properties = 0;
IOObjectRelease(drive); drive = 0;
}
IOIteratorReset(drivelist);
i_dsk->bytes = totalReadBytes;
o_dsk->bytes = totalWriteBytes;
}
次に、定期的に呼び出します。
io_stats i_dsk_t0;
io_stats o_dsk_t0;
getDISKcounters(drivelist, &i_dsk_t0, &o_dsk_t0);
// Wait 1s
io_stats i_dsk_t1;
io_stats o_dsk_t1;
getDISKcounters(drivelist, &i_dsk_t1, &o_dsk_t1);
この合計読み取り/書き込みバイトを取得したらすぐに、更新されたデータ間のデルタを作成する必要があります。例えば:
// t=0s
i_dsk_t0->bytes == 0 bytes
// t=1s
i_dsk_t1->bytes == 1000 bytes
delta = i_dsk_t1->bytes - i_dsk_t0->bytes
rate = delta/duration = delta/1s = 1000bytes/second
これはテストされていない短い分析ですが、期待どおりに機能するはずです。
より明確にするために、私が「デルタ」と呼んでいるものは、2 つの値の差にすぎません。レートが必要です。つまり、次のことを意味します。
rate = bytes read/written by seconds
bytes read/written for a period of N seconds
= --------------------------------------------
N seconds
ここで、システムの起動以降getDISKcounter
の読み取り/書き込みバイトの合計量(または別の絶対時間間隔ですが、実際には気にしません) を提供してください。したがって、限られた期間の読み取り/書き込みバイト数を取得するには、2 つの絶対結果の差を計算する必要があります。
B = total read/written bytes for N seconds = total read/written bytes since the system startup at time (X + N) - total read/written bytes since the system startup at time X
rate = B / N
これは単純な数学であり、複雑なことは何もありません。