状态机简介:
1 个有限状态机,也称为FSM(Finite State Machine),其在任意时刻都处于有限状态集合中的某一状态。当其获得一个输入字符时,将从当前状态转换到另一个状态,或者仍然保持在当前状态。在我看来,状态机的好处就是用于替代一系列的条件判断语句,具有很强的逻辑性,且极大解决了情况错漏的问题。
Rtthread下状态机软件包state_machine:
Rtthread框架下自带state_machine软件包,可用于不同状态之间的管理。一下面的代码为实例:
static struct state state_post = {
.state_parent = NULL,
.state_entry = NULL,
/* event_type, condition, guard, action, next_state */
.transitions = (struct transition[]){
{ EVENT_POST_BREAKON, NULL, NULL, &action_post_break, &state_postbreak },
{ EVENT_POST_ANSWER, (void*)1, &guard_post_fail, &action_post_fail, &state_postfail },
{ EVENT_POST_ANSWER, (void*)2, &guard_post_pass, &action_post_pass, &state_postpass },
},
.transition_nums = 3,
.data = "POST",
.action_entry = &state_post_enter,
.action_exti = &print_msg_exit,
};
上面的代码就代表状态机中的一个状态,当进入该状态时,首先执行本状态的action.entry函数,当接收到输入字符例如:“EVENT_POST_BREAKON”时,首先进行guard的判断,如果guard为NULL或者返回True,则表示可以进入该状态,此时先执行本状态的退出函数action_exti,而后执行状态转换函数action_post_break,这样便成功进入了下一个状态state_postbreak。这样即是状态机中状态转化的一个大致流程。
我在学习者一块时,一直有个疑问,就是既然执行完状态转换函数action_post_break后进入下一个状态执行下一个状态的action.entry函数,为什么不把这两个函数内容写到一块,状态转换函数的意义是什么?很简单的问题,但是我纠结了很久。使用状态转换函数的原因就是:会有很多状态转换到状态state_postbreak,不同状态转换之间一定会存在不同的处理情况和相同的处理情况,所以需要状态转换函数去处理状态间不同的处理情况,用action.entry去处理状态转换间相同的处理情况,即无论何种情况,转换到本状态都需要执行本状态的入口函数action.entry函数,但不同状态转换到本状态的状态转换函数是不一样的。
这里还会涉及到状态转换表中guard的存在意义,继续以上一个代码为例,当输入字符为:“EVENT_POST_ANSWER”时,可以转换到:“state_postfail ”和“state_postfail ”,这时就要通过“guard_post_fail”和“guard_post_pass”进行判断进入哪一个状态。