You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

如何针对不同产品标识配置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

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.08.02 04:15:37