搜尋
首頁運維linux運維有限狀態機FSM的實作與理解

有限狀態機FSM的實作與理解

Jun 25, 2017 am 10:05 AM
linux狀態理解程式設計

有限狀態機(finite state machine)簡稱FSM,表示有限個狀態及在這些狀態之間的轉移和動作等行為的數學模型,在計算機領域有著廣泛的應用。 FSM是一種邏輯單元內部的一種高效程式設計方法,在伺服器程式設計中,伺服器可以根據不同狀態或訊息類型進行相應的處理邏輯,使得程式邏輯清晰易懂。

那有限狀態機通常在什麼地方被用到?

處理程式語言或自然語言的tokenizer,自底向上解析語法的parser,
各種通訊協定發送者和接受方傳遞資料對訊息處理,遊戲AI等都有應用場景。

狀態機有以下幾種實作方法,我將一一闡述它們的優缺點。

一、使用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判斷語句,使得程式碼很低端,同時程式碼膨脹的比較厲害。這個狀態機的狀態僅有幾個,程式碼膨脹並不明顯,但是如果我們需要處理的狀態有數十個的話,該狀態機的程式碼就不好讀了。

二、使用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;
}

三、使用函數指標實作FSM

使用函數指標實作FSM的想法:建立對應的狀態表和動作查詢表,依照狀態表、事件、動作表定位對應的動作處理函數,執行完成後再進行狀態的切換。

當然使用函數指標實現的FSM的過程還是比較費時費力,但是這一切都是值得的,因為當你的程式規模大時候,基於這種表結構的狀態機,維護程序起來也是得心應手。

下面給出一個使用函數指標實作的FSM的框架:

我們還是以「小明的一天」為例設計出該FSM。

先給出該FSM的狀態轉移圖:
有限狀態機FSM的實作與理解

下面講解關鍵部分程式碼實作

##首先我們定義出小明一天的活動狀態

//比如我们定义了小明一天的状态如下
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>主函數我們這樣寫,然後觀察狀態機的運轉情況<p></p>
<pre class="brush:php;toolbar:false">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 %d\n", fsm.curState);
        test(&event); 
        sleep(1);  //休眠1秒,方便观察
    }

    return 0;
}
看一看此狀態機跑起來的狀態轉移情況:

有限狀態機FSM的實作與理解

上面的圖可以看出,當且僅當在指定的狀態下來了指定的事件才會發生函數的執行以及狀態的轉移,否則不會發生狀態的跳躍。這種機制使得這個狀態機不停地自動運轉,有條不絮地完成任務。

與前兩種方法相比,使用函數指標實作FSM能很好用於大規模的切換流程,只要我們實作搭好了FSM框架,以後進行擴充就很簡單了(只要在狀態表裡加一行來寫入新的狀態處理就可以了)。

需要FSM完整程式碼的童鞋請造訪我的github

#

以上是有限狀態機FSM的實作與理解的詳細內容。更多資訊請關注PHP中文網其他相關文章!

陳述
本文內容由網友自願投稿,版權歸原作者所有。本站不承擔相應的法律責任。如發現涉嫌抄襲或侵權的內容,請聯絡admin@php.cn
Linux操作系統的5個核心組件Linux操作系統的5個核心組件May 08, 2025 am 12:08 AM

Linux操作系統的5個核心組件是:1.內核,2.系統庫,3.系統工具,4.系統服務,5.文件系統。這些組件協同工作,確保系統的穩定和高效運行,共同構成了一個強大而靈活的操作系統。

Linux的5個基本要素:解釋Linux的5個基本要素:解釋May 07, 2025 am 12:14 AM

Linux的五個核心元素是:1.內核,2.命令行界面,3.文件系統,4.包管理,5.社區與開源。這些元素共同定義了Linux的本質和功能。

Linux操作:安全和用戶管理Linux操作:安全和用戶管理May 06, 2025 am 12:04 AM

Linux用戶管理和安全性可以通過以下步驟實現:1.創建用戶和組,使用命令如sudouseradd-m-gdevelopers-s/bin/bashjohn。 2.批量創建用戶和設置密碼策略,使用for循環和chpasswd命令。 3.檢查和修復常見錯誤,如家目錄和shell設置。 4.實施最佳實踐,如強密碼策略、定期審計和最小權限原則。 5.優化性能,使用sudo和調整PAM模塊配置。通過這些方法,可以有效管理用戶和提升系統安全性。

Linux操作:文件系統,進程等Linux操作:文件系統,進程等May 05, 2025 am 12:16 AM

Linux文件系統和進程管理的核心操作包括文件系統的管理和進程的控制。 1)文件系統操作包括創建、刪除、複製和移動文件或目錄,使用命令如mkdir、rmdir、cp和mv。 2)進程管理涉及啟動、監控和終止進程,使用命令如./my_script.sh&、top和kill。

Linux操作:外殼腳本和自動化Linux操作:外殼腳本和自動化May 04, 2025 am 12:15 AM

Shell腳本是Linux系統中用於自動化執行命令的強大工具。 1)Shell腳本通過解釋器逐行執行命令,處理變量替換和條件判斷。 2)基本用法包括備份操作,如使用tar命令備份目錄。 3)高級用法涉及使用函數和case語句管理服務。 4)調試技巧包括使用set-x開啟調試模式和set-e在命令失敗時退出。 5)性能優化建議避免子Shell,使用數組和優化循環。

Linux操作:了解核心功能Linux操作:了解核心功能May 03, 2025 am 12:09 AM

Linux是一個基於Unix的多用戶、多任務操作系統,強調簡單性、模塊化和開放性。其核心功能包括:文件系統:以樹狀結構組織,支持多種文件系統如ext4、XFS、Btrfs,使用df-T查看文件系統類型。進程管理:通過ps命令查看進程,使用PID管理進程,涉及優先級設置和信號處理。網絡配置:靈活設置IP地址和管理網絡服務,使用sudoipaddradd配置IP。這些功能在實際操作中通過基本命令和高級腳本自動化得以應用,提升效率並減少錯誤。

Linux:進入和退出維護模式Linux:進入和退出維護模式May 02, 2025 am 12:01 AM

進入Linux維護模式的方法包括:1.編輯GRUB配置文件,添加"single"或"1"參數並更新GRUB配置;2.在GRUB菜單中編輯啟動參數,添加"single"或"1"。退出維護模式只需重啟系統。通過這些步驟,你可以在需要時快速進入維護模式,並安全地退出,確保系統的穩定性和安全性。

了解Linux:定義的核心組件了解Linux:定義的核心組件May 01, 2025 am 12:19 AM

Linux的核心組件包括內核、shell、文件系統、進程管理和內存管理。 1)內核管理系統資源,2)shell提供用戶交互界面,3)文件系統支持多種格式,4)進程管理通過fork等系統調用實現,5)內存管理使用虛擬內存技術。

See all articles

熱AI工具

Undresser.AI Undress

Undresser.AI Undress

人工智慧驅動的應用程序,用於創建逼真的裸體照片

AI Clothes Remover

AI Clothes Remover

用於從照片中去除衣服的線上人工智慧工具。

Undress AI Tool

Undress AI Tool

免費脫衣圖片

Clothoff.io

Clothoff.io

AI脫衣器

Video Face Swap

Video Face Swap

使用我們完全免費的人工智慧換臉工具,輕鬆在任何影片中換臉!

熱工具

SublimeText3 Linux新版

SublimeText3 Linux新版

SublimeText3 Linux最新版

SublimeText3 英文版

SublimeText3 英文版

推薦:為Win版本,支援程式碼提示!

VSCode Windows 64位元 下載

VSCode Windows 64位元 下載

微軟推出的免費、功能強大的一款IDE編輯器

MantisBT

MantisBT

Mantis是一個易於部署的基於Web的缺陷追蹤工具,用於幫助產品缺陷追蹤。它需要PHP、MySQL和一個Web伺服器。請查看我們的演示和託管服務。

ZendStudio 13.5.1 Mac

ZendStudio 13.5.1 Mac

強大的PHP整合開發環境