Intel处理器macOS Monterey 12 Beta4下无法获取USB bsdname求助
问题根因
- macOS Monterey 12 Intel架构下,USB设备的
kIOBSDNameKey属性不再默认存储在kIOServicePlane下,而是被移到了kIODeviceTreePlane或者IOUSBPlane下,且Intel平台的USB驱动栈在Monterey上做了分层重构,BSD名称的挂载时机比Big Sur晚100-300ms左右,原有重试逻辑总时长足够,但递归搜索的平面配置错误才会一直返回nil。 - 额外注意:Intel平台下部分USB大容量存储设备的BSD名称是关联到其下的
IOBlockStorageDriver子节点,而非直接绑定在上层的usbDevice节点,递归搜索时如果没有开启父节点遍历权限也会找不到。
原有方案适配方法
你只需要修改IORegistryEntrySearchCFProperty的搜索平面参数,补充搜索选项即可:
void getBsdName(io_service_t usbDevice) { CFStringRef bsdName = NULL; // 优先搜索IODeviceTreePlane,再 fallback 到IOServicePlane const CFStringRef planes[] = {kIODeviceTreePlane, kIOServicePlane}; for(int i = 0; i < 500; i++) { for (int p = 0; p < sizeof(planes)/sizeof(planes[0]); p++) { bsdName = (CFStringRef)IORegistryEntrySearchCFProperty(usbDevice, planes[p], CFSTR(kIOBSDNameKey), kCFAllocatorDefault, // 增加遍历父节点的选项,避免子节点挂载在父层 kIORegistryIterateRecursively | kIORegistryIterateParents); if (bsdName) break; } if(!bsdName) { usleep(10000); continue; } printf("[%s]: Found bsd name for device %d.\n", __func__, usbDevice); CFRelease(bsdName); // 注意原有代码漏了CFRelease,会产生内存泄漏 break; } }
替代实现方案
如果不想依赖IORegistry的搜索逻辑,可以使用IOBSDNameMatching匹配方法直接获取对应BSD名称:
io_iterator_t iter = 0; kern_return_t kr = IOServiceGetMatchingServices(kIOMainPortDefault, IOBSDNameMatching(kIOMainPortDefault, 0, bsdNameStr), &iter); if (kr == KERN_SUCCESS) { io_service_t service = IOIteratorNext(iter); while (service) { // 处理匹配到的设备 IOObjectRelease(service); service = IOIteratorNext(iter); } IOObjectRelease(iter); }
也可以通过读取/dev/目录下的USB设备节点,结合statfs或者IOKit的设备路径匹配关联到对应的usbDevice实例,该方案兼容性更强,适配所有macOS版本和架构。
内容的提问来源于stack exchange,提问作者Crystal.Liu
相关产品推荐
相关产品推荐

