2010-01-17 29 views
7

Existe-t-il un moyen fiable, rapide et déterministe (par exemple et non un test de performances) pour vérifier si le lecteur système Mac OS X est sous tension?Comment détecter SSD sous Mac OS X?

Existe-t-il un autre indicateur de la façon dont le disque gère l'accès parallèle? J'essaie d'ajuster le nombre de threads que mon programme va utiliser pour les opérations liées au disque.

Je ne suis pas intéressé par la vitesse brute ou le temps de recherche, seul le type d'accès (série ou parallèle) est plus rapide pour le lecteur. Je ne m'attends pas à ce que les utilisateurs de mon programme utilisent iSCSI ou RAID. SSD est mon objectif, tout le reste est agréable à avoir.

Device Characteristics de IOAHCIBlockStorageDevice contient cette information. Comment puis-je le lire par programme?


Jusqu'à présent, j'ai compris il va comme ceci: (Voici 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. J'ai vérifié qu'il fonctionne avec Intel SSD et OCZ Vertex.

+0

Voir aussi http://stackoverflow.com/q/908188/545127 – Raedwald

Répondre

5

Si vous essayez d'obtenir ce genre d'information, vous êtes mieux de deviner que c'est IOKit.

Vous pouvez essayer certains de ses fonctionnalités à l'aide de l'outil de ligne de commande de ioreg ou IORegistryExplorer.


Voici un code qui pourrait vous aider. Il récupère tous les disques durs qui ne sont pas un RAID et ne sont pas des partitions. Ce n'est pas ce que vous voulez, mais cela pourrait vous aider à démarrer.

#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 
+0

@porneL: J'ai ajouté du code qui pourrait vous aider. –

+0

Merci. C'était très utile. Sans cela, j'utiliserais sans succès IOKit C++ API. – Kornel

+0

@porneL: On dirait que vous l'avez compris par vous-même. Je suppose que vous n'avez plus besoin d'aide sur cette question, n'est-ce pas? –

6

En fait, je pense que vous devriez aller sur la voie de l'analyse comparative, car il répond plus précisément à votre question - vous n'avez pas vraiment besoin que le disque soit vraiment un disque SSD. Que faire si l'utilisateur utilise une configuration RAID rapide ou une baie Fibre Channel ou utilise iSCSI?

Il suffit de lire un tas de secteurs aléatoires du sous-jacent/dev/DiskX et si elle répond à vos besoins, vous pouvez le traiter comme un « rapide » drive

+2

Je n'ai pas la mesure de référence de « rapide ». Je devrais exécuter deux benchmarks et comparer. Le temps consacré à l'analyse comparative fiable pourrait être plus long que le gain de temps en choisissant une meilleure stratégie. Un benchmark court ne sera pas fiable, et il est difficile de prendre en compte les caches, la latence, etc. Je suis à la recherche d'une solution rapide et déterministe. N'a pas besoin de supporter autre chose que SSD. – Kornel

+1

Assez juste mais je vais vous dire ceci, que c'est l'approche que le système d'exploitation Windows prend - si vous voyez un peu de statistiques, ce sera très facile à voir; exécuter 2 tests, l'un avec une lecture séquentielle vers l'arrière (c'est-à-dire le secteur 5, 4, 3, 2, etc.), puis un second avec une lecture de secteur aléatoire.Si la variance est fondamentalement la même, vous avez un SSD; sur les disques mécaniques, ils seront très différents –

0

Le nombre de threads? 1 va submerger n'importe quel disque, SSD, RAID ou pas. Le disque est lent, le processeur est rapide. Le système d'exploitation va réorganiser vos demandes de disque de toute façon (ou du moins il devrait) pour obtenir le moins de mouvements de la tête.

+0

Au moins sur Windows et Linux, le système d'exploitation ne réordonnera pas les demandes de disque pour les disques SSD –

+1

Selon mon expérience, OS X ne fait pas du bon travail en gérant l'accès au disque (accès parallèle). accès). Les threads liés à des E/S multiples qui accèdent au SSD sont plus rapides - peut-être juste parce qu'il y a un peu de surcharge CPU, mais ils sont néanmoins plus rapides. – Kornel