如何针对不同产品标识配置IOServiceAddMatchingNotification并验证代码正确性
关于多USB设备匹配通知的代码分析
你的这段代码能运行但存在严重问题,核心问题出在g_iteratorAdded的重复赋值上:
- 每次循环调用
IOServiceAddMatchingNotification时,都会把新的迭代器覆盖到同一个g_iteratorAdded变量里。这意味着只有最后一次循环创建的通知迭代器会被保留,前面的所有通知都会因为迭代器丢失而无法正常工作——后续无法通过迭代器处理已存在的设备,也无法正确管理通知的生命周期。
正确的实现方式
要支持多VID/PID组合的设备通知,你有两种可靠的方案:
方案1:使用单个匹配字典包含多个VID/PID组合
不需要循环创建多个通知,而是构建一个包含所有目标设备匹配规则的字典:
// 创建匹配字典 NSMutableDictionary* matchingDictionary = (NSMutableDictionary*)IOServiceMatching(kIOUSBDeviceClassName); // 创建VID的匹配数组 NSMutableArray* vidArray = [NSMutableArray array]; for (int n = 0; n < numberOfDevices; n++) { [vidArray addObject:[NSNumber numberWithLong:myVid[n]]]; } [matchingDictionary setObject:vidArray forKey:[NSString stringWithUTF8String:kUSBVendorID]]; // 创建PID的匹配数组 NSMutableArray* pidArray = [NSMutableArray array]; for (int n = 0; n < numberOfDevices; n++) { [pidArray addObject:[NSNumber numberWithLong:myPid[n]]]; } [matchingDictionary setObject:pidArray forKey:[NSString stringWithUTF8String:kUSBProductID]]; // 只创建一次通知 IOServiceAddMatchingNotification(g_notificationPort, kIOFirstMatchNotification, (CFMutableDictionaryRef)matchingDictionary, deviceAddedCallback, (void*)self, &g_iteratorAdded); // 必须迭代一次初始已连接的设备 IOReturn ret; io_service_t service; while ((service = IOIteratorNext(g_iteratorAdded))) { deviceAddedCallback((void*)self, service); IOObjectRelease(service); }
这种方式通过数组实现多值匹配,IOKit会自动匹配任意符合VID数组中任意值且对应PID数组中对应值的设备(注:VID和PID是按位置对应匹配,即myVid[0]对应myPid[0],myVid[1]对应myPid[1])。
方案2:为每个VID/PID组合保存独立的迭代器
如果需要为不同设备组合单独处理,可以维护一个迭代器数组,避免覆盖:
// 声明一个数组保存迭代器(比如作为类成员变量) NSMutableArray* addedIterators = [NSMutableArray array]; for (int n = 0; n < numberOfDevices; n++) { NSMutableDictionary* matchingDictionary = (NSMutableDictionary*)IOServiceMatching(kIOUSBDeviceClassName); [matchingDictionary setObject:[NSNumber numberWithLong:myVid[n]] forKey:[NSString stringWithUTF8String:kUSBVendorID]]; [matchingDictionary setObject:[NSNumber numberWithLong:myPid[n]] forKey:[NSString stringWithUTF8String:kUSBProductID]]; io_iterator_t iterator; IOServiceAddMatchingNotification(g_notificationPort, kIOFirstMatchNotification, (CFMutableDictionaryRef)matchingDictionary, deviceAddedCallback, (void*)self, &iterator); // 将迭代器加入数组保存 [addedIterators addObject:[NSValue valueWithPointer:iterator]]; // 处理当前已连接的对应设备 io_service_t service; while ((service = IOIteratorNext(iterator))) { deviceAddedCallback((void*)self, service); IOObjectRelease(service); } }
注意:在程序退出或不再需要通知时,要遍历数组释放所有迭代器,避免内存泄漏。
额外注意事项
- 必须调用
IOIteratorNext迭代初始已连接的设备,否则只会收到后续设备连接的通知,已存在的设备不会触发回调。 - 确保
g_notificationPort是正确初始化的(比如通过IONotificationPortCreate(kIOMasterPortDefault)创建),并且要在合适的时机释放。 - 回调函数
deviceAddedCallback中必须调用IOObjectRelease(service),避免资源泄漏。
内容的提问来源于stack exchange,提问作者fra87kdk
相关产品推荐
相关产品推荐

