网站首页 全球最实用的IT互联网站!

人工智能P2P分享Wind搜索发布信息网站地图标签大全

当前位置:诺佳网 > 电子/半导体 > 嵌入式技术 >

观察者模式在 RT-Thread 中的实现 | 技术集结

时间:2026-05-16 10:22

人气:

作者:admin

标签:

导读:在嵌入式系统中,模块间的高耦合和轮询机制往往带来资源浪费与响应延迟。观察者模式通过“发布-订阅”机制,能够以轻量级方式实现模块解耦与事件驱动。本文结合传感器更新、系...

在嵌入式系统中,模块间的高耦合和轮询机制往往带来资源浪费与响应延迟。观察者模式通过“发布-订阅”机制,能够以轻量级方式实现模块解耦与事件驱动。本文结合传感器更新、系统状态变化等典型场景,对比事件通知机制,并给出C语言代码实现,帮助开发者高效应用观察者模式。

目录


为啥要使用观察者模式


场景举例


观察者模式在嵌入式中的核心优点


观察者模式和事件通知对比


观察者模式代码实现

1 为啥要使用观察者模式

为了解决嵌入式系统中常见的模块解耦、事件驱动、低功耗响应 等核心问题。虽然 C 语言没有类和继承,但通过函数指针和结构体,完全可以轻量级实现观察者模式

2 场景举例

传感器数据更新

温度传感器每 500ms 采样一次

多个模块关心这个值:LCD 显示、日志记录、云端上报、过温告警

若每个模块都轮询读取 → 浪费 CPU、代码耦合高

用观察者模式:传感器“发布”数据,各模块“订阅” →事件驱动、按需响应

系统状态变化通知

网络连接状态(断开/重连)

电池电量低

OTA 升级完成

多个业务模块需做出反应(如 UI 刷新、保存上下文、关闭外设)

硬件中断与业务逻辑分离

按键中断触发 → 不能在 ISR 中做复杂处理

通过观察者通知应用层任务 →安全、可扩展

3 观察者模式在嵌入式中的核心优点

24b3f84a-50ce-11f1-ab55-92fbcf53809c.png

4 观察者模式和事件通知对比

4.1 功能特性对比

24daa40e-50ce-11f1-ab55-92fbcf53809c.png

4.2 使用场景分析

4.2.1 观察者模式适用场景

// 1. 传感器数据变化通知多个处理模块sensor_subject.notify(sensor_data);// 2. 系统状态变化广播system_state_subject.notify(new_state);// 3. 配置参数更新通知config_subject.notify(changed_params);

4.2.2 事件通知适用场景

// 1. 线程间同步等待特定条件rt_event_recv(event, EVENT_DATA_READY, RT_EVENT_FLAG_AND, timeout, &recved);// 2. 多个事件源的组合条件等待rt_event_recv(event, EVENT_A | EVENT_B, RT_EVENT_FLAG_OR, timeout, &recved);// 3. 异步任务完成通知rt_event_send(task_event, TASK_COMPLETED);

4.3 性能特点对比

观察者模式优势:

即时通知:无需等待,直接回调执行

数据丰富:可传递复杂数据结构指针

解耦性好:观察者与被观察者松耦合

扩展性强:易于添加新的观察者类型

事件通知优势:

标准IPC:符合RT-Thread IPC规范

阻塞等待:支持超时和非阻塞模式

条件组合:AND/OR逻辑组合等待

系统集成:与其他IPC机制统一管理

4.4 选择建议

选择观察者模式当:

需要立即响应状态变化

要传递复杂的数据结构

构建松耦合的组件架构

实现发布-订阅模式

选择事件通知当:

需要线程间同步等待

要求阻塞或超时机制

处理多种事件源的组合条件

利用RT-Thread标准IPC机制

5 观察者模式代码实现

observer.c

/*** @file observer.c* @brief 观察者模式实现文件* @author* @version 1.0* @date 2026-02-10** 基于RT-Thread rt_list实现的观察者模式具体实现*/#include"observer.h"#defineDBG_TAG "OBSERVER"#defineDBG_LVL DBG_INFO#include/*** @brief 初始化被观察者*/rt_err_tsubject_init(subject_t*subject){ RT_ASSERT(subject != RT_NULL); /* 初始化观察者链表 */ rt_list_init(&subject->observer_list); /* 运行时初始化自旋锁 */ rt_spin_lock_init(&subject->lock); LOG_D("Subject initialized"); returnRT_EOK;}/*** @brief 添加观察者*/rt_err_tsubject_add_observer(subject_t*subject,observer_t*observer){ rt_base_tlevel; RT_ASSERT(subject != RT_NULL); RT_ASSERT(observer != RT_NULL); RT_ASSERT(observer->update != RT_NULL); /* 关闭中断并获取自旋锁 */ level =rt_spin_lock_irqsave(&subject->lock); /* 检查观察者是否已经存在 */ rt_list_t*node; rt_list_for_each(node, &subject->observer_list) { observer_t*existing_observer =rt_list_entry(node,observer_t, list); if(existing_observer == observer) { rt_spin_unlock_irqrestore(&subject->lock, level); LOG_W("Observer already exists"); return-RT_ERROR; } } /* 添加观察者到链表尾部 */ rt_list_insert_before(&subject->observer_list, &observer->list); /* 恢复中断并释放自旋锁 */ rt_spin_unlock_irqrestore(&subject->lock, level); LOG_D("Observer added"); returnRT_EOK;}/*** @brief 移除观察者*/rt_err_tsubject_remove_observer(subject_t*subject,observer_t*observer){ rt_base_tlevel; rt_err_tresult = -RT_ERROR; RT_ASSERT(subject != RT_NULL); RT_ASSERT(observer != RT_NULL); /* 关闭中断并获取自旋锁 */ level =rt_spin_lock_irqsave(&subject->lock); /* 在链表中查找并移除观察者 */ rt_list_t*node, *temp; rt_list_for_each_safe(node, temp, &subject->observer_list) { observer_t*existing_observer =rt_list_entry(node,observer_t, list); if(existing_observer == observer) { rt_list_remove(node); result = RT_EOK; break; } } /* 恢复中断并释放自旋锁 */ rt_spin_unlock_irqrestore(&subject->lock, level); if(result == RT_EOK) { LOG_D("Observer removed"); } else { LOG_W("Observer not found"); } returnresult;}/*** @brief 通知所有观察者*/voidsubject_notify(subject_t*subject,void*data){ rt_base_tlevel; RT_ASSERT(subject != RT_NULL); /* 关闭中断并获取自旋锁 */ level =rt_spin_lock_irqsave(&subject->lock); /* 遍历所有观察者并调用更新函数 */ rt_list_t*node, *temp; rt_list_for_each_safe(node, temp, &subject->observer_list) { observer_t*observer =rt_list_entry(node,observer_t, list); if(observer->update != RT_NULL) { /* 恢复中断后再调用回调函数,避免在中断上下文中执行用户代码 */ rt_spin_unlock_irqrestore(&subject->lock, level); observer->update(observer, subject, data); level =rt_spin_lock_irqsave(&subject->lock); } } /* 恢复中断并释放自旋锁 */ rt_spin_unlock_irqrestore(&subject->lock, level); LOG_D("All observers notified");}/*** @brief 初始化观察者*/rt_err_tobserver_init(observer_t*observer,observer_update_func_tupdate,void*user_data){ RT_ASSERT(observer != RT_NULL); RT_ASSERT(update != RT_NULL); /* 初始化链表节点 */ rt_list_init(&observer->list); /* 设置回调函数和用户数据 */ observer->update = update; observer->user_data = user_data; LOG_D("Observer initialized"); returnRT_EOK;}/*** @brief 获取观察者数量*/intsubject_get_observer_count(subject_t*subject){ rt_base_tlevel; intcount =0; RT_ASSERT(subject != RT_NULL); /* 关闭中断并获取自旋锁 */ level =rt_spin_lock_irqsave(&subject->lock); /* 统计观察者数量 */ rt_list_t*node; rt_list_for_each(node, &subject->observer_list) { count++; } /* 恢复中断并释放自旋锁 */ rt_spin_unlock_irqrestore(&subject->lock, level); returncount;}

observer.h

/***@fileobserver.h*@brief观察者模式头文件*@author*@version1.0*@date2026-02-10** 基于RT-Thread rt_list实现的观察者模式* 支持添加观察者、移除观察者、通知观察者等功能*/#ifndef __OBSERVER_H__#define __OBSERVER_H__#include#include#ifdef __cplusplusextern"C"{#endif/***@brief观察者更新回调函数类型**@paramobserver 观察者指针*@paramsubject 被观察者指针*@paramdata 传递的数据*/typedefvoid(*observer_update_func_t)(void*observer,void*subject,void*data);/***@brief观察者结构体*/typedefstructobserver{ rt_list_tlist; /**< 链表节点,用于串连观察者 */    observer_update_func_t update;      /**< 更新回调函数 */    void *user_data;                    /**< 用户自定义数据 *

温馨提示:以上内容整理于网络,仅供参考,如果对您有帮助,留下您的阅读感言吧!
相关阅读
本类排行
相关标签
本类推荐

CPU | 内存 | 硬盘 | 显卡 | 显示器 | 主板 | 电源 | 键鼠 | 网站地图

Copyright © 2025-2035 诺佳网 版权所有 备案号:赣ICP备2025066733号
本站资料均来源互联网收集整理,作品版权归作者所有,如果侵犯了您的版权,请跟我们联系。

关注微信