分布式软总线能力位图机制设计
tips分布式软总线的能力位图底层设计实现其实就是侵入式链表没这方面基础的见链表学习侵入式链表-CSDN博客功能能力位图机制是软总线的能力资源管理的核心管理软总线所有已发布能力的聚合以及相关订阅者但是别被误导了上面功能不是有一张表管理open Harmony在这方面拆的很细。一、核心概念能力位图Capability Bitmap是发现模块中用来标识和匹配设备能力的机制。用一个uint32_t的每一位表示一种能力支持 14 种能力bit 0~13。二、能力位图在系统中的三套数据结构整个发现模块中能力位图相关的设计分布在两层、三套结构中三、三套结构详解① Manager 层g_capabilityList[16] — 能力分发索引static ListNode g_capabilityList[CAPABILITY_MAX_BITNUM]; // 16个链表本质以能力位为下标的倒排索引每个槽位挂载关注该能力的订阅者链表。g_capabilityList[0] (hicall) → 空 g_capabilityList[1] (profile) → 空 g_capabilityList[2] (visionPic) → 空 g_capabilityList[3] (castPlus) → 空 g_capabilityList[4] (aa) → 空 g_capabilityList[5] (dvKit) → 空 g_capabilityList[6] (ddmp) → DiscInfo(AppD订阅) → DiscInfo(AppE订阅) g_capabilityList[7] (osd) → 空 g_capabilityList[8] (share) → DiscInfo(AppF订阅) g_capabilityList[9] (approach) → 空 g_capabilityList[10] (vlink) → 空 g_capabilityList[11] (touch) → DiscInfo(AppG订阅) g_capabilityList[12] (oop) → 空 g_capabilityList[13] (oh_appr) → 空 g_capabilityList[14] → 空 g_capabilityList[15] → 空核心操作操作时机逻辑AddDiscInfoToCapabilityList订阅者注册遍历订阅者的 bitmap每个置1的位 → 挂到对应链表RemoveDiscInfoFromCapabilityList订阅者注销从链表中摘除该节点DiscOnDeviceFound远端设备被发现遍历设备的 bitmap每个置1的位 → 遍历对应链表 → 回调订阅者② CoAP 层g_publishMgr — 发布能力聚合器typedef struct { bool isUpdate; // 能力是否有变化需要重新注册到NSTACKX bool isEmpty; // 是否已全部清空 int16_t capCount[MAX_CAP_NUM]; // 每个能力的发布者数量引用计数 uint32_t allCap[CAPABILITY_NUM]; // 聚合后的总能力位图 SoftBusMutex lock; } DiscCoapInfo; static DiscCoapInfo *g_publishMgr NULL;本质多发布者的能力合并器用引用计数管理能力的生命周期。核心操作操作时机逻辑RegisterAllCapBitmap发布者注册遍历发布者的 bitmap每个置1的位 → capCount首次置1时 allCap 置位UnregisterAllCapBitmap发布者注销遍历发布者的 bitmap每个置1的位 → capCount--归零时 allCap 清位DiscCoapRegisterCapability(allCap)allCap 变化时将聚合位图注册到 NSTACKX驱动 CoAP 广播引用计数的作用App A Publish(share) → capCount[8]1, allCap | (18) → 广播 我有share App B Publish(share) → capCount[8]2, allCap 不变 → 广播内容不变 App A UnPublish → capCount[8]1, allCap 不变 → 广播内容不变(B还在发布) App B UnPublish → capCount[8]0, allCap 清除bit8 → 停止广播share能力③ CoAP 层g_subscribeMgr — 订阅能力聚合器结构与g_publishMgr完全相同但语义不同g_publishMgrg_subscribeMgrcapCount 含义有多少发布者发布了该能力有多少订阅者订阅了该能力allCap 含义本地设备对外声明的总能力本地设备扫描远端的总过滤器allCap 驱动DiscCoapRegisterCapability→ 广播DiscCoapSetFilterCapability→ 设置扫描过滤计数归零停止广播该能力停止过滤/扫描该能力四、完整结构关系图┌─────────────────────────────────────────────────────────────────────────┐ │ 应用层 (SDK) │ │ │ │ App A ─── Publish(ddmp) │ │ App B ─── Publish(share) │ │ App C ─── Publish(ddmp share) │ │ App D ─── Subscribe(ddmp) │ │ App E ─── Subscribe(ddmp touch) │ │ App F ─── Subscribe(share) │ └────────┬────────────────────────────────────────────────┬───────────────┘ │ 发布 │ 订阅 ▼ ▼ ┌─────────────────────────────────────────────────────────────────────────┐ │ Manager 层 (disc_manager.c) │ │ │ │ ┌── g_publishInfoList ──────────────┐ ┌── g_discoveryInfoList ──────┐│ │ │ │ │ ││ │ │ DiscItem(AppA) │ │ DiscItem(AppD) ││ │ │ └─ DiscInfo: Publish(ddmp) │ │ ├─ DiscInfo: Sub(ddmp) ││ │ │ │ │ └─ capNode → capList[6] ││ │ │ DiscItem(AppB) │ │ ││ │ │ └─ DiscInfo: Publish(share) │ │ DiscItem(AppE) ││ │ │ │ │ ├─ DiscInfo: Sub(ddmp ││ │ │ DiscItem(AppC) │ │ │ touch) ││ │ │ └─ DiscInfo: Publish(ddmpshare)│ │ ├─ capNode → capList[6] ││ │ │ │ │ └─ capNode → capList[11] ││ │ └────────────┬───────────────────────┘ │ ││ │ │ 转发到底层 │ DiscItem(AppF) ││ │ ▼ │ ├─ DiscInfo: Sub(share) ││ │ ┌── g_capabilityList[16] ──────────┐ │ └─ capNode → capList[8] ││ │ │ 能力分发索引(只挂订阅者) │ │ ││ │ │ │ └──────────────┬──────────────┘│ │ │ [6] ddmp → AppD → AppE │ │ │ │ │ [8] share → AppF │ │ │ │ │ [11] touch → AppE │ │ │ │ │ 其他 → 空 │ │ │ │ └──────────────────────────────────┘ │ │ │ ▲ │ │ │ │ 远端设备被发现时查表分发回调 │ │ └─────────┼──────────────────────────────────────────────┼──────────────┘ │ │ ▼ ▼ ┌─────────────────────────────────────────────────────────────────────────┐ │ CoAP 层 (disc_coap.c) │ │ │ │ ┌── g_publishMgr ─────────────────┐ ┌── g_subscribeMgr ─────────────┐│ │ │ 发布能力聚合器 │ │ 订阅能力聚合器 ││ │ │ │ │ ││ │ │ capCount[6] 2 (AppAAppC) │ │ capCount[6] 2 (AppDAppE) ││ │ │ capCount[8] 2 (AppBAppC) │ │ capCount[8] 1 (AppF) ││ │ │ capCount[11] 0 │ │ capCount[11] 1 (AppE) ││ │ │ │ │ ││ │ │ allCap ddmp | share │ │ allCap ddmp | share | touch ││ │ │ (16)|(18) 0x0140 │ │ 0x0900 | 0x0400 ││ │ │ │ │ 0x0D40 ││ │ │ │ │ │ │ ││ │ │ ▼ │ │ ▼ ││ │ │ DiscCoapRegisterCapability │ │ DiscCoapSetFilterCapability ││ │ │ → 注册到NSTACKX │ │ → 设置NSTACKX扫描过滤器 ││ │ │ → 驱动CoAP多播广播 │ │ → 驱动CoAP扫描 ││ │ └──────────────────────────────────┘ └───────────────────────────────┘│ │ │ │ ┌──────────────────────────────────────────────────────────────────┐ │ │ │ NSTACKX (DFinder) │ │ │ │ │ │ │ │ 广播: CoAP多播 → 本地有 ddmpshare 能力 │ │ │ │ 扫描: CoAP扫描 → 过滤 只关注有 ddmpsharetouch 的远端设备 │ │ │ └──────────────────────────────────────────────────────────────────┘ │ └─────────────────────────────────────────────────────────────────────────┘五、数据流从注册到发现的完整链路六、三套结构的对比总结维度① g_capabilityList② g_publishMgr③ g_subscribeMgr所在层ManagerCoAPCoAP数据结构ListNode[16]链表数组DiscCoapInfo含引用计数DiscCoapInfo含引用计数挂载内容订阅者 DiscInfo发布者的能力位图订阅者的能力位图核心语义谁在关注每个能力本地声明了哪些能力本地在扫描哪些能力用途设备发现时分发回调聚合后驱动广播聚合后驱动扫描过滤引用计数无链表本身即计数有capCount有capCount方向内部分发本地→本地对外广播本地→远端对内过滤远端→本地一句话总结g_publishMgr 聚合发布能力去广播我是谁g_subscribeMgr 聚合订阅能力去扫描找谁谁g_capabilityList 是发现事件到达时的倒排索引把找到了谁精准分发给谁在找。七、allcap计算比如当多个应用发布不同能力的时候coap层聚合他们App A 发布: capabilityBitmap share (bit 8) App B 发布: capabilityBitmap ddmp (bit 6) App C 发布: capabilityBitmap share (bit 8) touch (bit 11) 聚合结果: capCount[6] 1 (ddmp, 只有B发布) capCount[8] 2 (share, A和C都发布) capCount[11] 1 (touch, 只有C发布) allCap (16) | (18) | (111) 0x0900 ← 聚合位图16--0000 0000 0100 0000(18) --0000 0001 0000 0000(111) --0000 1000 0000 0000------------------------------------------------三个相或结果 0000 1001 0100 0000逐位对照结果转换成16进制0x0940哪个能力开启就把哪个位置置10x0940就是三个能力全开启。