如何检索读/写磁盘信息?

时间:2012-08-14 23:29:46

标签: objective-c macos

如何检索磁盘的特定读/写速率? (每秒写入的数据和每秒读取的数据,如活动监视器中所示)

注意我特别要求在OS X上提供Objective-C / C解决方案。

1 个答案:

答案 0 :(得分:4)

您可以查看XRG,它是OSX的活动监视器。整个磁盘统计信息抓取工具位于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

这只是一个未经测试的简短分析,但它应该按预期工作。


修改

更清楚的是,我称之为“delta”只是两个值之间的差异。你需要一个费率,这意味着:

rate = bytes read/written by seconds

       bytes read/written for a period of N seconds
     = --------------------------------------------
                        N seconds                           

现在,getDISKcounter只是给你自系统启动以来的读/写字节总数(或其他绝对时间间隔,但你真的不在乎)。因此,要在有限的时间内获得读/写字节数,您需要计算两个绝对结果之间的差异:

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

这只是简单的数学,这里没什么复杂的。