分布式软总线能力位图机制设计
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 |= (1<<8) → 广播 "我有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_publishMgr | g_subscribeMgr | |
|---|---|---|
| capCount 含义 | 有多少发布者发布了该能力 | 有多少订阅者订阅了该能力 |
| 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(ddmp+share)│ │ ├─ 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 (AppA+AppC) │ │ capCount[6] = 2 (AppD+AppE) ││
│ │ capCount[8] = 2 (AppB+AppC) │ │ capCount[8] = 1 (AppF) ││
│ │ capCount[11] = 0 │ │ capCount[11] = 1 (AppE) ││
│ │ │ │ ││
│ │ allCap = ddmp | share │ │ allCap = ddmp | share | touch ││
│ │ = (1<<6)|(1<<8) = 0x0140 │ │ = 0x0900 | 0x0400 ││
│ │ │ │ = 0x0D40 ││
│ │ │ │ │ │ ││
│ │ ▼ │ │ ▼ ││
│ │ DiscCoapRegisterCapability │ │ DiscCoapSetFilterCapability ││
│ │ → 注册到NSTACKX │ │ → 设置NSTACKX扫描过滤器 ││
│ │ → 驱动CoAP多播广播 │ │ → 驱动CoAP扫描 ││
│ └──────────────────────────────────┘ └───────────────────────────────┘│
│ │
│ ┌──────────────────────────────────────────────────────────────────┐ │
│ │ NSTACKX (DFinder) │ │
│ │ │ │
│ │ 广播: CoAP多播 → "本地有 ddmp+share 能力" │ │
│ │ 扫描: CoAP扫描 → 过滤 "只关注有 ddmp+share+touch 的远端设备" │ │
│ └──────────────────────────────────────────────────────────────────┘ │
└─────────────────────────────────────────────────────────────────────────┘
五、数据流:从注册到发现的完整链路


六、三套结构的对比总结
| 维度 | ① g_capabilityList | ② g_publishMgr | ③ g_subscribeMgr |
|---|---|---|---|
| 所在层 | Manager | CoAP | CoAP |
| 数据结构 | 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 = (1<<6) | (1<<8) | (1<<11) = 0x0900 ← 聚合位图
(1<<6)-->0000 0000 0100 0000
(1<<8) -->0000 0001 0000 0000
(1<<11) -->0000 1000 0000 0000
------------------------------------------------三个相或
结果: 0000 1001 0100 0000
逐位对照:

结果转换成16进制:0x0940
哪个能力开启就把哪个位置置1,0x0940就是三个能力全开启。
更多推荐


所有评论(0)