【经验分享】一种高内聚低耦合的消息分发模块的设计与实现
又到了每天的open话题:【代码面对面】时刻,让我们一起在摸鱼中学习技术吧。今天的话题是嵌入式的消息分发模块,你会怎么设计和实现?
1 写在前面
老套路,我先来,我给大家一个我在前东家的时候,做到一套非常灵活的消息分发模块,在里面的设计中,充分地把【高内聚低耦合】的分层思想体现了出来。
我们的整体架构图如后图所示:
2 消息处理的定义设计
这套消息分发模块很容易定义一套你自己的消息处理流程,在头文件开放了一个这样的宏定义,用于定义一个消息处理子模块:
#define DEFINE_MSG_HANDLER(name) \
static __attribute__((section(".rodata.MSG_HANDLE_OBJ_SECTION"))) msg_handler_obj_t msg_handler_##name##_obj = {\
.name = ##name;\
.handler = name##_hanler,\
};
3 子消息处理模块的实现
有了这个模块,比如我定义个OTA模块,只需要在ota_handler.c里面:
static int ota_handler(void)
{
//do your handle
}
DEFINE_MSG_HANDLER(ota)
比如我再需要定义个reboot模块,只需要在reboot_handler.c里面:
static int reboot_handler(void)
{
//do your handle
}
DEFINE_MSG_HANDLER(reboot)
4 链接脚本的修改
同时为了这套代码机制能够正确运行,我们还需要在gcc的ld脚本里面添加一些定义:
.rodata ALIGN(8) :
{
_msg_handler_start_obj = .;
*(.rodata.MSG_HANDLE_OBJ_SECTION)
_msg_handler_end_obj = .;
} > flash
5 消息分发模块的实现
有了以上的铺垫,我的消息分发模块就很简洁了,根本不需要关心消息是谁,怎么处理,它可以很方便去自己去找到对应的消息处理模块:
int msg_handle_entry(const char *msg_name)
{
msg_handler_obj_t *obj;
for (obj = _msg_handler_start_obj; obj < _msg_handler_end_obj; obj++) {
if (!strcmp(obj->name, msg_name)) {
//found msg handler obj
return obj->handler();
}
}
return -1;
}
而这个的另一个好处就是,如果你有新的消息模块,只需要仿造ota_handler.c写一个就好了,对外都看不到你消息内部的处理,最大化的解耦。
6 更多分享
最后,如果你对这套设计感兴趣的话,欢迎私信我获取源码。