如何在 Mac OS X 中检测 SSD?

发布于 2024-08-18 03:50:47 字数 1054 浏览 6 评论 0原文

是否有一种可靠、快速、确定性的方法(即不是基准)来检查 Mac OS X 所在的系统驱动器是否是固态驱动器?

还有其他指标可以表明磁盘处理并行访问的能力如何吗?我正在尝试调整我的程序将用于磁盘绑定操作的线程数。

我对原始速度或寻道时间不感兴趣,只对哪种类型的访问(串行或并行)对驱动器更快感兴趣。我不希望我的程序的用户使用 iSCSI 或 RAID。 SSD是我的重点,其他都很好。

IOAHCIBlockStorageDeviceDevice Characteristics 包含此信息。我如何以编程方式读取它?


到目前为止,我发现它是这样的:(以下是伪代码)

match = IOBSDNameMatching(kIOMasterPortDefault,0,"disk0s2");
IOServiceGetMatchingServices(kIOMasterPortDefault, match, &iterator);
while(entry = IOIteratorNext(iterator)) {
   do {
     entry = IORegistryEntryGetParentEntry(nextMedia, kIOServicePlane, &entry);
     dict = IORegistryEntryCreateCFProperty(nextMedia, 
            CFSTR(kIOPropertyDeviceCharacteristicsKey), kCFAllocatorDefault, 0);
     [dict objectForKey:CFSTR(kIOPropertyMediumTypeKey)];
   } 
   while(!dict && entry); 
}

编辑: 这是完整的源代码。我已经验证它可以与 Intel SSD 和 OCZ Vertex 配合使用。

Is there a reliable, quick, deterministic way (i.e. not a benchmark) to check whether the system drive Mac OS X is on is a Solid State Drive?

Is there any other indicator how well disk handles parallel access? I'm trying to adjust number of threads that my program is going to use for disk-bound operations.

I'm not interested in raw speed or seek time, only which type of access – serial or parallel – is faster for the drive. I don't expect users of my program to use iSCSI or RAID. SSD is my focus, anything else is nice-to-have.

Device Characteristics of IOAHCIBlockStorageDevice contains this information. How can I read it programmatically?


So far I've figured out it goes like this: (following is pseudocode)

match = IOBSDNameMatching(kIOMasterPortDefault,0,"disk0s2");
IOServiceGetMatchingServices(kIOMasterPortDefault, match, &iterator);
while(entry = IOIteratorNext(iterator)) {
   do {
     entry = IORegistryEntryGetParentEntry(nextMedia, kIOServicePlane, &entry);
     dict = IORegistryEntryCreateCFProperty(nextMedia, 
            CFSTR(kIOPropertyDeviceCharacteristicsKey), kCFAllocatorDefault, 0);
     [dict objectForKey:CFSTR(kIOPropertyMediumTypeKey)];
   } 
   while(!dict && entry); 
}

Edit: Here's complete source code. I've verified it works with Intel SSD and OCZ Vertex.

如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。

扫码二维码加入Web技术交流群

发布评论

需要 登录 才能够评论, 你可以免费 注册 一个本站的账号。

评论(4

人│生佛魔见 2024-08-25 03:50:47

实际上,我认为你应该走基准测试路线,因为它更准确地回答你的问题 - 你并不真正关心磁盘是否是 SSD,你只关心磁盘是否真的很快。如果用户使用快速 RAID 设置、光纤通道阵列或使用 iSCSI,该怎么办?

只需从底层 /dev/diskX 读取一堆随机扇区,如果它满足您的要求,您可以将其视为“快速”驱动器

Actually, I think you should go the benchmarking route, because it more accurately answers your question - you don't really care that the disk happens to be an SSD, you just care that the disk is really fast. What if the user is using a fast RAID setup, or a Fiber Channel array, or is using iSCSI?

Just read a bunch of random sectors from the underlying /dev/diskX and if it meets your requirements you can treat it as a "Fast" drive

-残月青衣踏尘吟 2024-08-25 03:50:47

如果您想获取此类信息,最好的猜测是 IOKit。

您可以使用ioreg命令行工具或IORegistryExplorer尝试它的一些功能。


这是一些可能对您有帮助的代码。它获取所有非 RAID 且非分区的硬盘驱动器。这不是您想要的,但它可能会帮助您开始。

#import "TWDevice.h"

#include <stdio.h>
#include <string.h>
#include <unistd.h>
#include <fcntl.h>
#include <sys/ioctl.h>
#include <errno.h>
#include <paths.h>
#include <sys/param.h>
#include <IOKit/IOKitLib.h>
#include <IOKit/IOBSD.h>
#include <IOKit/storage/IOMedia.h>
#include <CoreFoundation/CoreFoundation.h>
#include <IOKit/Kext/KextManager.h>


@implementation TWDevice

@synthesize name, devicePath, size, blockSize, writable, icon;

+ (NSArray *)allDevices {
    // create matching dictionary
    CFMutableDictionaryRef classesToMatch;
    classesToMatch = IOServiceMatching(kIOMediaClass);
    if (classesToMatch == NULL) {
        [NSException raise:@"TWError" format:@"Classes to match could not be created"];
    }

    // get iterator of matching services
    io_iterator_t mediaIterator;
    kern_return_t kernResult;
    kernResult = IOServiceGetMatchingServices(kIOMasterPortDefault,
                                                                      classesToMatch,
                                                                      &mediaIterator);

    if (kernResult != KERN_SUCCESS) {
        [NSException raise:@"TWError" format:@"Matching services did not succed."];
    }

    // iterate over all found medias
    io_object_t nextMedia;
    NSMutableArray *detectedDevices = [NSMutableArray array];
    while (nextMedia = IOIteratorNext(mediaIterator)) {
        NSMutableDictionary *properties;
        kernResult = IORegistryEntryCreateCFProperties(nextMedia,
                                                                                  (CFMutableDictionaryRef *)&properties,
                                                                                  kCFAllocatorDefault, 0);

        if (kernResult != KERN_SUCCESS) {
            [NSException raise:@"TWError" format:@"Getting properties threw error."];
        }

        // is it a whole device or just a partition?
        if ([[properties valueForKey:@"Whole"] boolValue] &&
            ![[properties valueForKey:@"RAID"] boolValue]) {
            TWDevice *device = [[[TWDevice alloc] init] autorelease];

            device.devicePath = [NSString stringWithFormat:@"%sr%@", _PATH_DEV, [properties valueForKey:@"BSD Name"]];
            device.blockSize = [[properties valueForKey:@"Preferred Block Size"] unsignedLongLongValue];
            device.writable = [[properties valueForKey:@"Writable"] boolValue];
            device.size = [[properties valueForKey:@"Size"] unsignedLongLongValue];

            io_name_t name;
            IORegistryEntryGetName(nextMedia, name);
            device.name = [NSString stringWithCString:name encoding:NSASCIIStringEncoding];

            …

            [detectedDevices addObject:device];
        }

        // tidy up
        IOObjectRelease(nextMedia);
        CFRelease(properties);
    }
    IOObjectRelease(mediaIterator);

    return detectedDevices;
}

@end

If you're trying to get that kind of information, you're best guess is IOKit.

You can try some of it's functionality using the ioreg command line tool or the IORegistryExplorer.


Here's some code that might help you. It fetches all hard drives that aren't a RAID and aren't partitions. This isn't what you want, but it might get you started.

#import "TWDevice.h"

#include <stdio.h>
#include <string.h>
#include <unistd.h>
#include <fcntl.h>
#include <sys/ioctl.h>
#include <errno.h>
#include <paths.h>
#include <sys/param.h>
#include <IOKit/IOKitLib.h>
#include <IOKit/IOBSD.h>
#include <IOKit/storage/IOMedia.h>
#include <CoreFoundation/CoreFoundation.h>
#include <IOKit/Kext/KextManager.h>


@implementation TWDevice

@synthesize name, devicePath, size, blockSize, writable, icon;

+ (NSArray *)allDevices {
    // create matching dictionary
    CFMutableDictionaryRef classesToMatch;
    classesToMatch = IOServiceMatching(kIOMediaClass);
    if (classesToMatch == NULL) {
        [NSException raise:@"TWError" format:@"Classes to match could not be created"];
    }

    // get iterator of matching services
    io_iterator_t mediaIterator;
    kern_return_t kernResult;
    kernResult = IOServiceGetMatchingServices(kIOMasterPortDefault,
                                                                      classesToMatch,
                                                                      &mediaIterator);

    if (kernResult != KERN_SUCCESS) {
        [NSException raise:@"TWError" format:@"Matching services did not succed."];
    }

    // iterate over all found medias
    io_object_t nextMedia;
    NSMutableArray *detectedDevices = [NSMutableArray array];
    while (nextMedia = IOIteratorNext(mediaIterator)) {
        NSMutableDictionary *properties;
        kernResult = IORegistryEntryCreateCFProperties(nextMedia,
                                                                                  (CFMutableDictionaryRef *)&properties,
                                                                                  kCFAllocatorDefault, 0);

        if (kernResult != KERN_SUCCESS) {
            [NSException raise:@"TWError" format:@"Getting properties threw error."];
        }

        // is it a whole device or just a partition?
        if ([[properties valueForKey:@"Whole"] boolValue] &&
            ![[properties valueForKey:@"RAID"] boolValue]) {
            TWDevice *device = [[[TWDevice alloc] init] autorelease];

            device.devicePath = [NSString stringWithFormat:@"%sr%@", _PATH_DEV, [properties valueForKey:@"BSD Name"]];
            device.blockSize = [[properties valueForKey:@"Preferred Block Size"] unsignedLongLongValue];
            device.writable = [[properties valueForKey:@"Writable"] boolValue];
            device.size = [[properties valueForKey:@"Size"] unsignedLongLongValue];

            io_name_t name;
            IORegistryEntryGetName(nextMedia, name);
            device.name = [NSString stringWithCString:name encoding:NSASCIIStringEncoding];

            …

            [detectedDevices addObject:device];
        }

        // tidy up
        IOObjectRelease(nextMedia);
        CFRelease(properties);
    }
    IOObjectRelease(mediaIterator);

    return detectedDevices;
}

@end
苦妄 2024-08-25 03:50:47

这似乎仅适用于内部驱动器。我找不到使用 IOKit 查询三星 T5 外置 USB 3 SSD 的 SSD 性能的方法(也没有找到东芝 Canvio USB HDDD)。不过,我确实管理了 MBP 中的内部驱动器。

磁盘实用程序也不认为三星是SSD,所以这让我认为除了测量实际性能之外可能没有其他方法。

This only seems possible for internal drives. I could not find a way using IOKit to query a Samsung T5 external USB 3 SSD for its SSD-ness (nor a Toshiba Canvio USB HDDD). I did manage for the internal drive in my MBP, though.

Disk utility also doesn’t think the Samsung is an SSD, so that makes me think there may not be a way, other than to measure actual performance.

多像笑话 2024-08-25 03:50:47

线程数? 1 将会压倒任何磁盘,无论是否是 SSD、RAID。磁盘速度慢,处理器速度快。无论如何,操作系统都会对您的磁盘请求进行重新排序(或者至少应该这样做),以获得最少的磁头移动。

The number of threads? 1 is going to overwhelm any disk, SSD, RAID or not. Disk is slow, processor is fast. The OS is going to reorder your disk requests anyhow (or at least it should) to get the least head movements.

~没有更多了~
我们使用 Cookies 和其他技术来定制您的体验包括您的登录状态等。通过阅读我们的 隐私政策 了解更多相关信息。 单击 接受 或继续使用网站,即表示您同意使用 Cookies 和您的相关数据。
原文