Как обнаружить SSD в Mac OS X?
Есть ли надежный, быстрый, детерминированный способ (т.е. не тестирование), чтобы проверить, является ли системный диск Mac OS X твердотельным накопителем?
Есть ли другой показатель того, насколько хорошо диск обрабатывает параллельный доступ? Я пытаюсь настроить количество потоков, которые моя программа собирается использовать для операций с диском.
Меня не интересует сырая скорость или время поиска, только какой тип доступа - последовательный или параллельный - быстрее для накопителя. Я не ожидаю, что пользователи моей программы будут использовать iSCSI или RAID. SSD - мой фокус, все остальное приятно иметь.
Device Characteristics
из IOAHCIBlockStorageDevice
содержит эту информацию. Как я могу прочитать это программно?
До сих пор я понял, что это выглядит так: (следующий псевдокод)
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 и OCZ Vertex.
3 ответа
Если вы пытаетесь получить такую информацию, лучше всего предположить, что это 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
На самом деле, я думаю, что вы должны пойти по пути бенчмаркинга, потому что он более точно отвечает на ваш вопрос - вас действительно не волнует, что диск является SSD, вы просто заботитесь о том, чтобы диск был действительно быстрым. Что, если пользователь использует быструю настройку RAID или массив Fibre Channel или iSCSI?
Просто прочитайте несколько случайных секторов из базового /dev/diskX и, если он соответствует вашим требованиям, вы можете рассматривать его как "быстрый" диск
Это кажется возможным только для внутренних дисков. Мне не удалось найти способ с помощью IOKit запросить внешний SSD-накопитель USB 3 Samsung T5 на предмет его SSD (ни Toshiba Canvio USB HDDD). Тем не менее, я справился с внутренним диском в моем MBP.
Дисковая утилита также не думает, что Samsung - это SSD, поэтому я думаю, что другого способа, кроме как измерить фактическую производительность, может не быть.
Количество потоков? 1 собирается сокрушить любой диск, SSD, RAID или нет. Диск медленный, процессор быстрый. Операционная система все равно будет переупорядочивать запросы к диску (или, по крайней мере, так), чтобы получить наименьшее количество движений головы.