Iceoryx(冰羚):通知机制是如何实现的(源码解析)
为什么需要通知机制(Notify)
当订阅端游数据时可以及时被唤醒,减少CPU资源占用
涉及技术
1. 观察者模式
单个Publisher , 多个Subscriber都能被通知到
2. 信号量
底层依赖信号量实现夸进程通知
操作系统提供的原语:
- sem_wait() — 没有信号 → 线程从 CPU 调度队列移除,零 CPU 占用
- sem_post() — 发信号 → 把等待的线程放回调度队列,微秒级唤醒
Iceoryx(冰羚)实现方式
1. 信号量 需要跨进程使用,所以创建后需要被放在共享内存中
ConditionVariableData(信号量对象):
- 在创建 WaitSet / Listener 对象时 由Roudi创建,具体接口:runtime::PoshRuntime::getInstance().getMiddlewareConditionVariable() 分配
- 当用户调用Listener的attachEvent时会被放到 ChunkQueueData 对象中
补充:WaitSet / Listener中有除了信号量,还有通知槽,允许多个Subscriber对象进行订阅
ChunkQueueData
- 说明:Subscriber侧的共享内存队列订阅成功后队列地址可被Publisher拿到
- 位置: 管理段共享内存(Subscriber 的数据队列)
- 作用: Subscriber 端的消息队列 + 通知绑定信息
内部变量:
-
RelativePointer<ConditionVariableData> m_conditionVariableDataPtr (信号量)
-
m_conditionVariableNotificationIndex (信号槽位置)
2. 通知
在Publisher端,调用流程:
publish()>>>
ChunkDistributor::deliverToAllStoredQueues >>>
ChunkQueuePusher::push >>>
ConditionNotifier(*getMembers()->m_conditionVariableDataPtr.get(),
*getMembers()->m_conditionVariableNotificationIndex)
.notify();
说明:m_conditionVariableDataPtr / m_conditionVariableNotificationIndex 在 Publisher端被拿到,直接使用m_conditionVariableDataPtr sem_post(),m_conditionVariableNotificationIndex告诉对端,是哪个Subscriber
3. 接收
Listener和WaitSet调用 wait(), 就会一直阻塞线程,直到监听的其中一个Subscriber的信号量被触发
4. Listener和WaitSet的区别
Listener内部有thread,执行了wait,同时客户注册了回调被存储在Event中,轮训通知槽掉用对用的回调对象;
listener.attachEvent(subscriber, SubscriberEvent::DATA_RECEIVED, callback);
// → m_conditionVariableDataPtr 也被设置了
WaitSet需要用户自动执行wait,并自己轮训判断拿到wait接口返回的不同的subscriber,执行不同的操作
waitSet.attachState(subscriber, HAS_DATA);
while (true) {
auto notifications = waitSet.wait();
// ...
}
// → m_conditionVariableDataPtr 被设置了
总结
冰羚融合了信号量和观察者模式,在共享内存上实现了跨进程的Publisher和Susbcriber之间的信号通知功能,非常值得学习!!~
AtomGit 是由开放原子开源基金会联合 CSDN 等生态伙伴共同推出的新一代开源与人工智能协作平台。平台坚持“开放、中立、公益”的理念,把代码托管、模型共享、数据集托管、智能体开发体验和算力服务整合在一起,为开发者提供从开发、训练到部署的一站式体验。
更多推荐


所有评论(0)