基于C语言写的一个系统,斗胆投稿园子首页,写错的地方欢迎各位拍砖,谢谢!

最近转战G+C项目,在MTK上挂载VIA的芯片,自己被安排维护开机和模式切换导致的子系统状态的管理,原来的设计通过一个中央函数的调用,还有无数全局变量的控制来实现负责的状态机管理,让我花了好几个工作日去理解他的实现思路,不过这个是已经量产过的代码了,不能对她做很多的改动,所以内心里一直想把这个代码重写的欲望压抑到现在,经过自己几个晚上的努力终于得到完成。现在贴出来跟大家分享一下。

系统需求背景:对于一个系统,他可能存在很多状态,这些状态会随着系统的变化不断进行切换,而且在其状态变化的过程中随时可能有其他的事件发生以改变其状态切换的方向,当然当这个事件发生时系统所处的状态可能是其中的任一状态。
举自己代码的实现的通用例子来讲,子系统的状态可能处于关机,开机中,开机,系统启动中,系统正常运行,系统关闭中,关机中等等状态,状态之间的变化是递进的,不能跳跃的。
同时我们的母系统随时可能期望子系统以某种形式运行,他会发消息通知子系统,这种消息传来的时候,不管子系统当前处于什么状态都必须改变自己前进的步伐,很快的转换到母系统期望的发展方向去切换。我在这里将这个消息称之为事件。
这些事件分为:开机,系统启动,关机(这里我将系统关闭和开机归为了一类,如果不是一类在AnpherSystemManager中增加一类事件即可)
这就使得整个情况变的复杂,母系统随时会要求子系统相应其想要的各种事件,而子系统又可能处于各种状态,而且各种状态又随时需要发生切换。
虽然可以用一个中央函数加无数的switch case 可以实现这个功能,也会很稳定,但怎样写易懂的,高聚合的代码来实现这个系统,是我这段时间一直十分苦恼的一件事情,如果你也在为这件事情苦恼,我可以告诉你,你可以参考我的代码。
作者:张素丰 转载请注明出处:http://www.zhangsufeng.cn/?p=299

系统实现:这里讲下我的思路:1.为了易懂和可拓展性,需要将数据和代码(处理过程分开),也就是不管有多少状态,有多少事件,我都需要将其当做统一的对象来进行处理,当然状态的变化又分为主动变化和被动变化,这个在系统中叶有所考虑。

//系统过程状态位
typedef  enum
{
 STATE_PWROFF,//关机状态
 STATE_WAIT_PWRUP,//等待系统开机
 STATE_PWRUP,//已开机
 STATE_WAIT_RUN,//等待系统正常运行
 STATE_RUN,//运行中
 STATE_WAIT_PWROFF,//等待关机中

//add item befor here
 SYSTEM_STATE_MAX
}anpher_system_state_enum;

 

//系统事件(需要清楚系统最终状态位)
typedef  enum
{
 EVENT_PWRUP,//使系统裸机运行
 EVENT_RUN ,//配置环境使其正常运行
 EVENT_PWROFF,//关机

//add item befor here
 SYSTEM_EVENT_MAX
}anpher_system_event_enum;

2.增加全局控制的参数
//全局配置参数的结构体
typedef struct
{
 anpher_system_event_enum curr_event;
 anpher_system_state_enum curr_state;
}anpher_system_status_tcb;

//全局配置变量
static anpher_system_status_tcb anpher_curr_status={EVENT_PWROFF,STATE_PWROFF};//Default 关机状态

3.定义全局处理的事件和状态切换大的模型:也就是定义每一个事件和每一个状态所对应的触发的动作,切换到下一个状态或事件后,再通过这个表来找到自己对应的处理动作,对应如果需要增加事件或者状态的话在这里添加相应的处理过程即可。
/*********************************************************
//Modal 层配置信息
**********************************************************/
//系统事件-->系统最终状态位
//状态切换配置表,从这里查询从某一状态切换到其他状态所需要进行的动作
static VoidFuncPtr OperationTable[SYSTEM_STATE_MAX][SYSTEM_EVENT_MAX]=
{
 //STATE_PWROFF,//关机状态
 {
  Func_FirstWaitPwron,//EVENT_PWRUP
  Func_FirstWaitPwron,//EVENT_RUN
  Func_ToPwroff,//EVENT_PWROFF
 }
 //STATE_WAIT_PWRUP,//等待系统开机
 ,{
  Func_ResetWaitPwron,//EVENT_PWRUP
  Func_ResetWaitPwron,//EVENT_RUN
  Func_ToWaitPwroff,//EVENT_PWROFF
 }
 //STATE_PWRUP,//已开机
 ,{
  Func_ToPwron,//EVENT_PWRUP
  Func_ToWaitRun,//EVENT_RUN
  Func_ToWaitPwroff,//EVENT_PWROFF
 }
 //STATE_WAIT_RUN,//等待系统正常运行
 ,{
  Func_ResetWaitPwron,//EVENT_PWRUP
  Func_ToWaitRun,//EVENT_RUN
  Func_ToWaitPwroff,//EVENT_PWROFF
 }
 //STATE_RUN,//运行中
 ,{
  Func_ResetWaitPwron,//EVENT_PWRUP
  Func_ToRun,//EVENT_RUN
  Func_ToWaitPwroff,//EVENT_PWROFF
 }
 //STATE_WAIT_PWROFF,//等待关机中
 ,{
  Func_FirstWaitPwron,//EVENT_PWRUP
  Func_FirstWaitPwron,//EVENT_RUN
  Func_ToPwroff,//EVENT_PWROFF
 }
};
4.上面定义了处理模型,下面就要定义事件或状态的触发动作(这个是核心的处理,一般不会改动)
/*********************************************************
//Control  触发器
**********************************************************/
void anpher_set_event(anpher_system_event_enum event)
{
 assert(event<SYSTEM_EVENT_MAX);
 anpher_curr_status.curr_event = event;
}
void anpher_change_state(anpher_system_state_enum state)
{
 assert(state<SYSTEM_STATE_MAX);
 anpher_curr_status.curr_state = state;
}
void anpher_update_system_state(void)
{
 VoidFuncPtr FuncPtr =0;
 anpher_system_state_enum curr_state = anpher_curr_status.curr_state;
 
 assert(curr_state<SYSTEM_STATE_MAX);
 FuncPtr = OperationTable[curr_state][anpher_curr_status.curr_event];
 FuncPtr();
 }
5.下面就是定义一些切换的接口,这里会开始考虑主动变化和被动切换,被动切换在anpher_change_state(state)或anpher_set_event(event)后直接anpher_update_system_state()即可,主动变化则需要在anpher_change_state(state)或anpher_set_event(event)后直接调用自己想要的动作即可。
/*********************************************************
//interface
**********************************************************/


//空函数 Do Nothing
static void DoNullFunc(void)
{
 //this do null
}
//不能状态跳跃的情况,执行断言
static void DoNAFunc(void)
{
 assert(0);
}

//系统处理函数
//每个EVENT最终的state状态需要子系统上报解析完成后执行anpher_change_state(state),然后执行anpher_update_system_state
static void Func_FirstWaitPwron(void)  //主动
{
 //system form pwroff to wait pwron
 anpher_change_state(STATE_WAIT_PWRUP);
 Func_FirstWaitPwron_interface();
}
static void Func_ResetWaitPwron(void)  //主动
{
 //system form reset to wait pwron
 anpher_change_state(STATE_WAIT_PWRUP);
 Func_ResetWaitPwron_interface();
}
static void Func_ToPwron(void)    //被动
{
 //这里定义的是pwron 后进行的补充动作
 Func_ToPwron_interface();
}
static void Func_ToWaitRun(void)//主动
{
 anpher_change_state(STATE_WAIT_RUN);
 Func_ToWaitRun_interface();
}
static void Func_ToRun(void)   //被动
{
 //这里定义的是system run 后进行的补充动作
 Func_ToRun_interface();
}
static void Func_ToWaitPwroff(void) //主动
{
 anpher_change_state(STATE_WAIT_PWROFF);
 Func_ToWaitPwroff_interface();
}
static void Func_ToPwroff(void)  //被动
{
 //这里定义的是pwroff 后进行的补充动作
 Func_ToPwroff_interface();
}
(上述思路已经在MinGWStudio中编译通过,理论上可以实现跨平台)
期望与各位致力于系统设计的同行交流沟通,QQ275000205,Email:zhangsufeng@gmail.com

补问博客园各位大牛:上述的方法是不是跟面向对象中的MVC有些相似?还有哪些差距?


 

 

作者: 张素丰 发表于 2010-11-30 00:19 原文链接

推荐.NET配套的通用数据层ORM框架:CYQ.Data 通用数据层框架
新浪微博粉丝精灵,刷粉丝、刷评论、刷转发、企业商家微博营销必备工具"