您的位置:时时app平台注册网站 > 时时app平台注册网站 > Linux编程之有限状态机FSM的理解与实现

Linux编程之有限状态机FSM的理解与实现

2019-11-01 11:50

零星状态机(finite state machine)简单的称呼FSM,表示有限个情状及在这么些景况之间的转变和动作等作为的数学模型,在微型计算机世界有着广大的接受。FSM是风姿罗曼蒂克种逻辑单元内部的生龙活虎种高效编制程序方法,在服务器编制程序中,服务器能够依靠分化境况只怕音信类型举办相应的管理逻辑,使得程序逻辑清晰易懂。

三、使用函数指针完毕FSM

采取函数指针完成FSM的思路:创立相应的状态表和动作查询表,依照状态表、事件、动作表定位相应的动作管理函数,试行到位后再展开景况的切换。

理所必然使用函数指针达成的FSM的进度或然比较费时费事,不过这一切都是值得的,因为当您的顺序层面大时候,基于这种表结构的状态机,维护程序起来也是贯虱穿杨。

上边给出八个运用函数指针完结的FSM的框架:

我们依旧以“小明的一天”为例设计出该FSM。

先付给该FSM的场合转移图:
图片 1

下边疏解关键部分代码完成

第生龙活虎我们定义出小多美滋(Aptamil)天的活动状态

//比如我们定义了小明一天的状态如下
enum
{
    GET_UP,
    GO_TO_SCHOOL,
    HAVE_LUNCH,
    DO_HOMEWORK,
    SLEEP,
};

我们也定义出会产生的平地风波

enum
{
    EVENT1 = 1,
    EVENT2,
    EVENT3,
};

概念状态表的数据结构

typedef struct FsmTable_s
{
    int event;   //事件
    int CurState;  //当前状态
    void (*eventActFun)();  //函数指针
    int NextState;  //下一个状态
}FsmTable_t;

接下去定义出最关键FSM的状态表,我们全体FSM正是基于这一个概念好的表来运维的。

FsmTable_t XiaoMingTable[] =
{
    //{到来的事件,当前的状态,将要要执行的函数,下一个状态}
    { EVENT1,  SLEEP,           GetUp,        GET_UP },
    { EVENT2,  GET_UP,          Go2School,    GO_TO_SCHOOL },
    { EVENT3,  GO_TO_SCHOOL,    HaveLunch,    HAVE_LUNCH },
    { EVENT1,  HAVE_LUNCH,      DoHomework,   DO_HOMEWORK },
    { EVENT2,  DO_HOMEWORK,     Go2Bed,       SLEEP },

    //add your codes here
};

状态机的挂号、状态转移、事件管理的动作落实

/*状态机注册*/
void FSM_Regist(FSM_t* pFsm, FsmTable_t* pTable)
{
    pFsm->FsmTable = pTable;
}

/*状态迁移*/
void FSM_StateTransfer(FSM_t* pFsm, int state)
{
    pFsm->curState = state;
}

/*事件处理*/
void FSM_EventHandle(FSM_t* pFsm, int event)
{
    FsmTable_t* pActTable = pFsm->FsmTable;
    void (*eventActFun)() = NULL;  //函数指针初始化为空
    int NextState;
    int CurState = pFsm->curState;
    int flag = 0; //标识是否满足条件
    int i;

    /*获取当前动作函数*/
    for (i = 0; i<g_max_num; i  )
    {
        //当且仅当当前状态下来个指定的事件,我才执行它
        if (event == pActTable[i].event && CurState == pActTable[i].CurState)
        {
            flag = 1;
            eventActFun = pActTable[i].eventActFun;
            NextState = pActTable[i].NextState;
            break;
        }
    }


    if (flag) //如果满足条件了
    {
        /*动作执行*/
        if (eventActFun)
        {
            eventActFun();
        }

        //跳转到下一个状态
        FSM_StateTransfer(pFsm, NextState);
    }
    else
    {
        // do nothing
    }
}

主函数我们那样写,然后观看状态机的运作意况

int main()
{
    FSM_t fsm;
    InitFsm(&fsm);
    int event = EVENT1; 
    //小明的一天,周而复始的一天又一天,进行着相同的活动
    while (1)
    {
        printf("event %d is coming...n", event);
        FSM_EventHandle(&fsm, event);
        printf("fsm current state %dn", fsm.curState);
        test(&event); 
        sleep(1);  //休眠1秒,方便观察
    }

    return 0;
}

看一看该情状机跑起来的情况转移状态:

图片 2

上边的图能够看见,当且仅当在钦点的气象下去了钦赐的风浪才会发生函数的实施以至气象的转换,否则不会产生景况的跳转。这种体制使得那一个状态机不停地自动运维,有条不絮地做到职责。

与前两种办法比较,使用函数指针达成FSM能很好用于大面积的切换流程,只要我们贯彻搭好了FSM框架,以往进行扩充就很简短了(只要在场馆表里加风姿浪漫行来写入新的气象管理就能够了)。

急需FSM完整代码的童鞋请访谈我的github

意况机有以下三种实现方式,笔者将各样解说它们的得失。

二、使用switch实现FSM

利用switch语句完毕的FSM的布局变得愈加明显了,其症结也是明显的:这种设计情势即使简易,通过一大堆剖断来管理,相符小框框的情况切换流程,但假如局面扩展难以扩充和维护。

int main()
{
    int state = GET_UP;
    //小明的一天
    while (1)
    {

        switch(state)
        {
        case GET_UP:
            GetUp(); //具体调用的函数
            state = GO_TO_SCHOOL;  //状态的转移
            break;
        case GO_TO_SCHOOL:
            Go2School();
            state = HAVE_LUNCH;
            break;
        case HAVE_LUNCH:
            HaveLunch();
            state = GO_HOME;
            break;
            ...
        default:
            break;
        }
    }

    return 0;
}

那有限状态机日常在哪些地点被用到?

生龙活虎、使用if/else if语句完毕的FSM

应用if/else if语句是兑现的FSM最简便易行最易懂的主意,大家只必要经过大气的if /else if语句来判断状态值来实行相应的逻辑管理。

拜谒上边的例证,我们选择了汪洋的if/else if语句达成了三个简单的状态机,做到了依据情形的两样实施相应的操作,并且达成了事态的跳转。

//比如我们定义了小明一天的状态如下
enum
{
    GET_UP,
    GO_TO_SCHOOL,
    HAVE_LUNCH,
    GO_HOME,
    DO_HOMEWORK,
    SLEEP,
};


int main()
{
    int state = GET_UP;
    //小明的一天
    while (1)
    {
        if (state == GET_UP)
        {
            GetUp(); //具体调用的函数
            state = GO_TO_SCHOOL;  //状态的转移
        }
        else if (state == GO_TO_SCHOOL)
        {
            Go2School();
            state = HAVE_LUNCH;
        }
        else if (state == HAVE_LUNCH)
        {
            HaveLunch();
        }
        ...
        else if (state == SLEEP)
        {
            Go2Bed();
            state = GET_UP;
        }
    }

    return 0;
}

看完上边的例证,我们有哪些感受?是或不是深感程序即使简易易懂,可是利用了大气的if推断语句,使得代码好低档,同期代码膨胀的可比厉害。这一个状态机的事态唯有多少个,代码膨胀并不刚烈,但是生机勃勃旦咱们需求管理的状态有数十二个的话,该状态机的代码就不好读了。

管理程序语言依然自然语言的 tokenizer,自底向上深入分析语法的parser,
种种通讯合同发送方和选用者传递数据对新闻管理,游戏AI等皆有利用场景。

本文由时时app平台注册网站发布于时时app平台注册网站,转载请注明出处:Linux编程之有限状态机FSM的理解与实现

关键词:

  • 上一篇:7.14
  • 下一篇:没有了