3

我正在尝试从 USB 设备 BSD 名称获取该设备的实际安装卷,例如设备的 BSD 名称为“disk2”,并在“/Volumes/USBSTICK”上安装一个 BSD 名称为“disk2s1”的卷。

这是我到目前为止一直在做的事情。使用

NSNotificationCenter NSWorkspaceDidMountNotification

我检测到何时添加了驱动器。然后我扫描所有 USB 设备并使用

IORegistryEntrySearchCFProperty kIOBSDNameKey

获取设备的 BSD 名称。

对于我的 U 盘,这将返回“disk2”。跑步

system_profiler SPUSBDataTypesystem_profiler SPUSBDataType

节目

      Product ID: 0x5607
      Vendor ID: 0x03f0  (Hewlett Packard)
      Serial Number: AA04012700008687
      Speed: Up to 480 Mb/sec
      Manufacturer: HP
      Location ID: 0x14200000 / 25
      Current Available (mA): 500
      Current Required (mA): 500
      Capacity: 16.04 GB (16,039,018,496 bytes)
      Removable Media: Yes
      Detachable Drive: Yes
      BSD Name: disk2
      Partition Map Type: MBR (Master Boot Record)
      S.M.A.R.T. status: Not Supported
      Volumes:
        USBSTICK:
          Capacity: 16.04 GB (16,037,879,808 bytes)
          Available: 5.22 GB (5,224,095,744 bytes)
          Writable: Yes
          File System: MS-DOS FAT32
          BSD Name: disk2s1
          Mount Point: /Volumes/USBSTICK
          Content: Windows_FAT_32

这是有道理的,因为单个 USB 设备可能有多个卷。

我以为我可以使用 DiskArbitration 来找到实际的卷,但是

DASessionRef session = DASessionCreate(NULL);
if (session)
{
    DADiskRef disk = DADiskCreateFromBSDName(NULL,session,"disk2");
    if (disk)
    {
        CFDictionaryRef dict = DADiskCopyDescription(disk);
        if (dict)

总是返回一个 NULL 字典。

那么,如何从 USB 设备的 BSD 名称获取该设备的实际安装卷?我想应该可以遍历所有卷,获取它们的 BSD 名称并检查它是否以字符串开头,例如上面的 /Volumes/USBSTICK 是“disk2s1”,但这很麻烦,如果有 disk20 等怎么办?

4

1 回答 1

3

找到使用 IOBSDNameMatching 的解决方案将创建一个字典以将服务与给定的 BSD 名称匹配。然后可以搜索该服务的子级以查找它们的 BSD 名称。注意:这是我第一次在 OSX 上做任何事情。此外,由于错误,上述代码中的 'dict' 为 NULL,但无论如何该字典对此毫无用处。

这是一些没有错误检查等的精简代码。

CFMutableDictionaryRef  matchingDict;

matchingDict = IOBSDNameMatching(kIOMasterPortDefault, 0, "disk2");
io_iterator_t itr;
// Might only ever be one service so, MatchingService could be used. No sure though
IOServiceGetMatchingServices(kIOMasterPortDefault, matchingDict, &itr);
io_object_t service;
while ((service = IOIteratorNext(itr)))
{
    io_iterator_t children;
    io_registry_entry_t child;

    // Obtain the service's children.
    IORegistryEntryGetChildIterator(service, kIOServicePlane, &children);
    while ((child = IOIteratorNext(children)))
    {
        CFTypeRef name = IORegistryEntrySearchCFProperty(child,
                                                      kIOServicePlane,
                                                      CFSTR(kIOBSDNameKey),
                                                      kCFAllocatorDefault,
                                                      kIORegistryIterateRecursively);
        if (name)
        {
            // Got child BSD Name e.g. "disk2s1"
        }
    }
}
于 2014-11-03T15:07:02.167 回答