版权声明:本文为博主原创文章,遵循 CC 4.0 BY-SA 版权协议,转载请附上原文出处链接和本声明。
本文链接:https://blog.csdn.net/MINGTING1323/article/details/100186598
在上一篇https://blog.csdn.net/MINGTING1323/article/details/100173420介绍了模块化编程思想,但实际应用中具体应该怎么实现呢?古人云“知行合一”,道理谁都懂,但真正到了应用的时候可能又为难了。在这,我想到了很好地思路,就是我很好的借鉴linux驱动代码去实现。
linux驱动代码很好的实现了模块化思想。需要加载驱动可以insmod加载或取消。每个模块的代码通过module_init()注册和module_exit()函数进行卸载。同时像外部提供了open,close,write,read,等相同的外部接口。用户新增驱动时,只需要填充struct file_operations结构体即可。这样部分模块没有加载也不影响其他模块的正常使用。因此,我们也借鉴这个思路实现模块化代码。
另外一个思路就是各个模块编译成.so,我们只需要将接口提供给使用者即可。
结合两种思路。我们的代码没实现ismod注册功能,但实现类似module_init()相关功能。但可以根据实际需求,进行修改。也可以修改为读取配置.so进行加载。
首先,我们要明确每个模块应该做什么事。我很抽象的出了三件事:一.做自己的事(相当于下面的CALLBACK_FUNC)。二.做别人的交代的事。三.给别人予以回馈 APP_COMMAND。除了这三件事应该没有其他。
typedef void * APP_HANDLE ;
typedef int ( * CALLBACK_FUNC ) ( APP_HANDLE * head, void* pdata, void* pparam ) ;
typedef int ( * APP_MESSAGE ) ( int sender, void * msg ) ;
typedef int ( * APP_COMMAND ) ( int op, int ilen, void * ibuf, int olen, void * obuf ) ;
typedef void *(*THREAD_FUNC)(void*) ;
其次,我们设计出模块的结构如下。每个模块对外接口都是一样的send_message,与do_command,好比驱动里面的open,write。
typedef void * SYSTEM_CONFIG ;
//模块信息结构
typedef struct
{
char * description ; //模块名称
int id ; //模块ID
APP_MESSAGE send_message ; //模块消息接收处理函数
APP_COMMAND do_command ; //模块处理函数
} APP_MODULE ;
再次,我们应该定义模块结构。模块之间的通讯接口如下:
//系统消息结构
typedef struct
{
int sender ; //发送模块
int receiver ; //接受模块
int command ; //命令字
int length ; //内容长度
char data[BASE_PACK_LEN] ; //内容,
} KERNEL_MESSAGE;
统一管理所有模块的结构体如下:
typedef struct _tagAPP_MODULE_LIST
{
char name[64];
APP_HANDLE handle ; //记录so的句柄
APP_INIT app_init ;
APP_EXIT app_exit ;
APP_MODULE * module ; //模块输出函数等
struct _tagAPP_MODULE_LIST * next ;
} APP_MODULE_LIST ;
typedef struct
{
char * name ; //模块名称
APP_INIT init ; //模块注册
APP_EXIT exit ; //模块退出
} INTERNAL_MODULE ;
对外接口提供的两种方式的模块调用时如下:
/////////////////////////////////////////////////////////
// Function : CORE_send_message
// Description : send message to one module
// Input :
// Output :
//发送消息,无返回数据
int CORE_send_message( KERNEL_MESSAGE * msg )
{
APP_MODULE_LIST * app, * call = NULL ;
int ret = 0 ;
if( core_context == NULL )
return 0 ;
pthread_mutex_lock( &core_context->module_mutex ) ;
app = core_context->module ;
while( app != NULL )
{
if( app->module->id == msg->receiver && app->module->send_message != NULL )
{
call = app ;
break ;
}
app = app->next ;
}
pthread_mutex_unlock( &core_context->module_mutex ) ;
if( call )
{
ret = call->module->send_message( msg->sender, msg ) ;
//LOG_PRINTF("msg->sender is %d \n",(msg->sender));
}
return ret ;
}
/////////////////////////////////////////////////////////
// Function : CORE_do_command
// Description : ask other module to execute one command
// Input :
// Output :
//执行一个命令,可以有返回值
int CORE_do_command ( int module, int op, int ilen, void * ibuf, int olen, void * obuf )
{
APP_MODULE_LIST * app, * call = NULL ;
int ret = 0;
if( core_context == NULL )
return 0 ;
pthread_mutex_lock( &core_context->module_mutex ) ;
app = core_context->module ;
while( app != NULL )
{
if( app->module->id == module && app->module->do_command != NULL )
{
call = app ;
break ;
}
app = app->next ;
}
pthread_mutex_unlock( &core_context->module_mutex ) ;
if( call )
ret = call->module->do_command( op, ilen, ibuf, olen, obuf ) ;
return ret ;
}
后续还将提供一份代码,以app_sysctrl模块提供一份示例,希望大家能够喜欢。
代码路径:https://download.csdn.net/download/mingting1323/11647276。
————————————————
版权声明:本文为CSDN博主「mingting1323」的原创文章,遵循 CC 4.0 BY-SA 版权协议,转载请附上原文出处链接及本声明。
原文链接:https://blog.csdn.net/MINGTING1323/article/details/100186598