有限状态机(有限状态机)简称FSM,表示有限个状态及在这些状态之间的转移和动作等行为的数学模型,在计算机领域有着广泛的应用.FSM是一种逻辑单元内部的一种高效编程方法,在服务器编程中,服务器可以根据不同状态或者消息类型进行相应的处理逻辑,使得程序逻辑清晰易懂。
处理程序语言或者自然语言的记号赋予器,自底向上解析语法的解析器,
各种通信协议发送方和接受方传递数据对消息处理,游戏AI等都有应用场景。
状态机有以下几种实现方法,我将一一阐述它们的优缺点。
<强>一、使用if/else if语句实现的FSM
>强使用if/else if语句是实现的FSM最简单最易懂的方法,我们只需要通过大量的if/else if语句来判断状态值来执行相应的逻辑处理。
看看下面的例子,我们使用了大量的if/else if语句实现了一个简单的状态机,做到了根据状态的不同执行相应的操作,并且实现了状态的跳转。
//比如我们定义了小明一天的状态如下 枚举 { GET_UP, GO_TO_SCHOOL, HAVE_LUNCH, GO_HOME, DO_HOMEWORK, 睡眠, }; int main () { int状态=GET_UP;//小明的一天 而(1) { 如果(状态==GET_UP) { 服饰();//具体调用的函数 状态=GO_TO_SCHOOL;//状态的转移 } else if(国家==GO_TO_SCHOOL) { Go2School (); 状态=HAVE_LUNCH; } else if(国家==HAVE_LUNCH) { HaveLunch (); } … else if(睡眠状态==) { Go2Bed (); 状态=GET_UP; } } 返回0; } >之前看完上面的例子,大家有什么感受?是不是感觉程序虽然简单易懂,但是使用了大量的如果判断语句,使得代码很低端,同时代码膨胀的比较厉害。这个状态机的状态仅有几个,代码膨胀并不明显,但是如果我们需要处理的状态有数十个的话,该状态机的代码就不好读了
。<强>二、使用开关实现FSM
强>使用开关语句实现的FSM的结构变得更为清晰了,其缺点也是明显的:这种设计方法虽然简单,通过一大堆判断来处理,适合小规模的状态切换流程,但如果规模扩大难以扩展和维护。
int main () { int状态=GET_UP;//小明的一天 而(1) { 开关(状态) { 案例GET_UP: 服饰();//具体调用的函数 状态=GO_TO_SCHOOL;//状态的转移 打破; 案例GO_TO_SCHOOL: Go2School (); 状态=HAVE_LUNCH; 打破; 案例HAVE_LUNCH: HaveLunch (); 状态=GO_HOME; 打破; … 默认值: 打破; } } 返回0; } >之前<强>三、使用函数指针实现FSM
强>使用函数指针实现FSM的思路:建立相应的状态表和动作查询表,根据状态表,事件,动作表定位相应的动作处理函数,执行完成后再进行状态的切换。
当然使用函数指针实现的FSM的过程还是比较费时费力,但是这一切都是值得的,因为当你的程序规模大时候,基于这种表结构的状态机,维护程序起来也是得心应手。
下面给出一个使用函数指针实现的FSM的框架:
我们还是以“小明的一天”为例设计出该FSM。
先给出该FSM的状态转移图:
下面讲解关键部分代码实现
首先我们定义出小明一天的活动状态
//比如我们定义了小明一天的状态如下 枚举 { GET_UP, GO_TO_SCHOOL, HAVE_LUNCH, DO_HOMEWORK, 睡眠, }; >之前我们也定义出会发生的事件
枚举 { EVENT1=1, EVENT2, EVENT3, }; >之前定义状态表的数据结构
typedef struct FsmTable_s { int事件;//事件 int CurState;//当前状态 空白(* eventActFun) ();//函数指针 int NextState;//下一个状态 }FsmTable_t; >之前接下来定义出最重要FSM的状态表,我们整个FSM就是根据这个定义好的表来运转的。
Linux有限状态机FSM的理解与实现