【经验分享】一种高内聚低耦合的消息分发模块的设计与实现

【经验分享】一种高内聚低耦合的消息分发模块的设计与实现

又到了每天的open话题:【代码面对面】时刻,让我们一起在摸鱼中学习技术吧。今天的话题是嵌入式的消息分发模块,你会怎么设计和实现?

1 写在前面

老套路,我先来,我给大家一个我在前东家的时候,做到一套非常灵活的消息分发模块,在里面的设计中,充分地把【高内聚低耦合】的分层思想体现了出来。

我们的整体架构图如后图所示:

image-20230517181401417

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写一个就好了,对外都看不到你消息内部的处理,最大化的解耦。

image-20230517181116879

6 更多分享

最后,如果你对这套设计感兴趣的话,欢迎私信我获取源码。

猜你喜欢

转载自blog.csdn.net/szullc/article/details/130733394