女人夜夜春高潮爽A∨片传媒_国产精品VIDEOS麻豆_在线精品亚洲一区二区三区_亚洲熟妇无码av

編程代碼
新聞詳情

什么是狀態機?用C語言實現進程5狀態模型

發布(bu)時間:2020-12-07 09:27:47 最后更(geng)新:2020-12-07 09:35:00 瀏覽次數:3896

什么是狀態機?

定義

狀態機(ji)(ji)是有限狀態自動機(ji)(ji)的簡稱,是現實事物運行(xing)規則抽象(xiang)而成的一個數學模型。

先來(lai)解釋什(shen)么是(shi)“狀(zhuang)態”( State )。現實事(shi)物(wu)是(shi)有(you)不同狀(zhuang)態的,例如一(yi)個(ge)LED等(deng),就有(you) 亮 和(he) 滅兩種狀(zhuang)態。我們通常所說(shuo)的狀(zhuang)態機(ji)是(shi)有(you)限(xian)狀(zhuang)態機(ji),也就是(shi)被描述的事(shi)物(wu)的狀(zhuang)態的數量是(shi)有(you)限(xian)個(ge),例如LED燈的狀(zhuang)態就是(shi)兩個(ge) 亮和(he) 滅。

狀態(tai)機,也(ye)就是 State Machine ,不是指(zhi)一臺(tai)實際機器(qi),而(er)是指(zhi)一個數學(xue)模型。說白了(le),一般就是指(zhi)一張狀態(tai)轉換圖。

舉(ju)例

以物理(li)課(ke)學的(de)燈(deng)泡圖(tu)為例,就是(shi)一個最基(ji)本(ben)的(de)小型狀態機

什么是狀態機?用C語言實現進程5狀態模型

可以畫出以下的狀態機(ji)圖

什么是狀態機?用C語言實現進程5狀態模型

這里就(jiu)是兩(liang)個(ge)狀態:①燈泡亮,②燈泡滅 如果打開開關(guan),那(nei)么狀態就(jiu)會切換為(wei) 燈泡亮 。燈泡亮 狀態下如果關(guan)閉開關(guan),狀態就(jiu)會切換為(wei) 燈泡滅。

狀(zhuang)(zhuang)(zhuang)態(tai)(tai)機(ji)(ji)的(de)全稱是有限狀(zhuang)(zhuang)(zhuang)態(tai)(tai)自動機(ji)(ji),自動兩個(ge)字也(ye)是包含重要含義的(de)。給(gei)定(ding)一個(ge)狀(zhuang)(zhuang)(zhuang)態(tai)(tai)機(ji)(ji),同時給(gei)定(ding)它的(de)當前狀(zhuang)(zhuang)(zhuang)態(tai)(tai)以及輸入,那(nei)么(me)輸出狀(zhuang)(zhuang)(zhuang)態(tai)(tai)時可以明確的(de)運算出來的(de)。例(li)如對于燈(deng)泡,給(gei)定(ding)初始狀(zhuang)(zhuang)(zhuang)態(tai)(tai)燈(deng)泡滅(mie) ,給(gei)定(ding)輸入“打開開關(guan)”,那(nei)么(me)下一個(ge)狀(zhuang)(zhuang)(zhuang)態(tai)(tai)時可以運算出來的(de)。

四大概念

下面來給出狀態(tai)機的四大概(gai)念。

  1. State ,狀(zhuang)(zhuang)態。一(yi)個狀(zhuang)(zhuang)態機(ji)至少(shao)要包含兩個狀(zhuang)(zhuang)態。例(li)如上面燈泡的例(li)子(zi),有 燈泡亮和 燈泡滅兩個狀(zhuang)(zhuang)態。

  2. Event ,事件(jian)(jian)(jian)。事件(jian)(jian)(jian)就(jiu)(jiu)是執行某(mou)個操作的觸發條件(jian)(jian)(jian)或者口令。對于燈泡,“打開開關”就(jiu)(jiu)是一個事件(jian)(jian)(jian)。

  3. Action ,動作(zuo)(zuo)。事(shi)件發(fa)生以后要執行動作(zuo)(zuo)。例如事(shi)件是(shi)“打開(kai)開(kai)關”,動作(zuo)(zuo)是(shi)“開(kai)燈”。編程的時候(hou),一(yi)個 Action 一(yi)般(ban)就對(dui)應一(yi)個函數。

  4. Transition ,變換。也就(jiu)是從一個(ge)狀(zhuang)態變化為另一個(ge)狀(zhuang)態。例如“開燈過程”就(jiu)是一個(ge)變換。

狀態機的應用

狀態機是(shi)一個對真實(shi)世界(jie)的(de)抽象,而且(qie)是(shi)邏(luo)輯嚴謹的(de)數(shu)(shu)學抽象,所以(yi)明顯非常(chang)適(shi)合用在數(shu)(shu)字(zi)領域。可以(yi)應用到各個層面上,例如硬件設(she)計,編譯(yi)器(qi)設(she)計,以(yi)及編程實(shi)現各種具體業務邏(luo)輯的(de)時(shi)候。



進程5狀態模型(xing)

進(jin)(jin)程管理是Linux五大子系(xi)統之一,非(fei)常重要,實(shi)際實(shi)現(xian)起來(lai)非(fei)常復雜,我們來(lai)看下進(jin)(jin)程是如何切(qie)換狀態的。

下圖是進(jin)程的5狀(zhuang)態模(mo)型:

什么是狀態機?用C語言實現進程5狀態模型

關于該(gai)圖簡(jian)單(dan)介紹如下:

  1. 可(ke)(ke)運(yun)(yun)行態:當(dang)進程(cheng)正在被(bei)CPU執行,或已(yi)經準備就緒(xu)(xu)隨(sui)時可(ke)(ke)由調度程(cheng)序執行,則(ze)稱該(gai)進程(cheng)為(wei)處于運(yun)(yun)行狀態(running)。進程(cheng)可(ke)(ke)以在內核態運(yun)(yun)行,也可(ke)(ke)以在用(yong)戶態運(yun)(yun)行。當(dang)系統資源已(yi)經可(ke)(ke)用(yong)時,進程(cheng)就被(bei)喚醒而(er)進入準備運(yun)(yun)行狀態,該(gai)狀態稱為(wei)就緒(xu)(xu)態。

  2. 淺度睡眠(mian)態(可中斷(duan)(duan)):進程正(zheng)在睡眠(mian)(被阻(zu)塞),等待資源到來是喚(huan)醒,也可以通過其他進程信號(hao)或時鐘(zhong)中斷(duan)(duan)喚(huan)醒,進入運行隊列(lie)。

  3. 深度(du)睡(shui)眠(mian)態(不(bu)可(ke)中斷):其(qi)和淺(qian)度(du)睡(shui)眠(mian)基本(ben)類似(si),但有一點就是不(bu)可(ke)由(you)其(qi)他進程信號(hao)或時鐘中斷喚醒(xing)。只有被使用(yong)wake_up函數明(ming)確喚醒(xing)時才能轉換到可(ke)運行(xing)的就緒狀態。

  4. 暫停狀(zhuang)態(tai):當進(jin)程收到(dao)(dao)信號(hao)SIGSTOP、SIGTSTP、SIGTTIN或SIGTTOU時就會進(jin)入暫停狀(zhuang)態(tai)。可向其發送SIGCONT信號(hao)讓進(jin)程轉換到(dao)(dao)可運(yun)行狀(zhuang)態(tai)。

  5. 僵(jiang)死(si)狀(zhuang)態:當進(jin)程(cheng)已停止運行,但其父進(jin)程(cheng)還沒有詢問其狀(zhuang)態時,未釋放PCB,則稱該進(jin)程(cheng)處于僵(jiang)死(si)狀(zhuang)態。

進程的(de)狀態(tai)就(jiu)是按照這個狀態(tai)圖進行(xing)切換的(de)。

該(gai)狀態流程有點復(fu)雜,因為(wei)我們目標只(zhi)是實現(xian)一個簡單的狀態機,所以我們簡化一下(xia)該(gai)狀態機如(ru)下(xia):

什么是狀態機?用C語言實現進程5狀態模型

要想(xiang)實現狀態機(ji),首先(xian)將該狀態機(ji)轉(zhuan)換成(cheng)下面的狀態遷(qian)移表(biao)。

什么是狀態機?用C語言實現進程5狀態模型

簡要(yao)說明(ming)如(ru)下(xia):假設(she)當前進程(cheng)處于(yu)running狀(zhuang)(zhuang)態下(xia),那么(me)只有(you)schedule事件(jian)發生(sheng)之后,該進程(cheng)才會產(chan)生(sheng)狀(zhuang)(zhuang)態的(de)遷移(yi),遷移(yi)到owencpu狀(zhuang)(zhuang)態下(xia),如(ru)果在(zai)此狀(zhuang)(zhuang)態下(xia)發生(sheng)了(le)其(qi)他的(de)事件(jian),比如(ru)wake、wait_event都不會導致狀(zhuang)(zhuang)態的(de)遷移(yi)。

如上圖所示:

  1. 每(mei)一(yi)列表示(shi)一(yi)個(ge)狀態,每(mei)一(yi)行對(dui)應一(yi)個(ge)事件。

  2. 該表是實現狀態機的(de)最核(he)心的(de)一個圖,請讀者詳細對比該表和狀態遷移圖的(de)的(de)關(guan)系。

  3. 實際(ji)場景中,進程的(de)(de)切換會遠比這(zhe)(zhe)個圖復雜(za),好在眾多大神都幫我們(men)解(jie)決了這(zhe)(zhe)些復雜(za)的(de)(de)問題,我們(men)只(zhi)需要站在巨人的(de)(de)肩膀上就可以了。



實(shi)現(xian)

根據狀(zhuang)態遷移表,定(ding)義該(gai)狀(zhuang)態機的狀(zhuang)態如下(xia):

typedef enum {
sta_origin=0,
sta_running,sta_owencpu,sta_sleep_int,sta_sleep_unint}State;

發生的事件如下:

typedef enum{
evt_fork=0,
evt_sched,evt_wait,evt_wait_unint,evt_wake_up,evt_wake,}EventID;

不(bu)論是(shi)狀(zhuang)態還是(shi)事件都可以根據實際情況增加(jia)調整。

定義一(yi)個結(jie)構體用來表示當前狀態轉換信(xin)息:

typedef struct {
State curState;//當前狀(zhuang)態
EventID eventId;//事件ID
State nextState;//下(xia)個狀態
CallBack action;//回調函數,事件發生后,調用對應的(de)回調函數
}StateTransform ;

事件(jian)回調函數(shu):實際應(ying)用(yong)中(zhong)不(bu)同的(de)事件(jian)發生需要(yao)執行不(bu)同的(de)action,就需要(yao)定義(yi)不(bu)同的(de)函數(shu), 為方(fang)便起見,本例所(suo)有的(de)事件(jian)都(dou)統(tong)一使用(yong)同一個回調函數(shu)。功(gong)能:打印事件(jian)發生后(hou)進(jin)程的(de)前后(hou)狀態,如(ru)果(guo)狀態發生了變(bian)化,就調用(yong)對應(ying)的(de)回調函數(shu)。

void action_callback(void *arg)
{StateTransform *statTran = (StateTransform *)arg;if(statename[statTran->curState] == statename[statTran->nextState])
{printf("invalid event,state not change\n");
}else{
printf("call back state from %s --> %s\n",
statename[statTran->curState],statename[statTran->nextState]);}}

為各個狀態定義(yi)遷移表數組:

/*origin*/
StateTransform stateTran_0={{sta_origin,evt_fork, sta_running,action_callback},{sta_origin,evt_sched, sta_origin,},{sta_origin,evt_wait, sta_origin,},{sta_origin,evt_wait_unint, sta_origin,},{sta_origin,evt_wake_up, sta_origin,},{sta_origin,evt_wake, sta_origin,},};/*running*/
StateTransform stateTran_1={{sta_running,evt_fork, sta_running,},{sta_running,evt_sched, sta_owencpu,action_callback},{sta_running,evt_wait, sta_running,},{sta_running,evt_wait_unint, sta_running,},{sta_running,evt_wake_up, sta_running,},{sta_running,evt_wake, sta_running,},};/*owencpu*/
StateTransform stateTran_2={{sta_owencpu,evt_fork, sta_owencpu,},{sta_owencpu,evt_sched, sta_owencpu,},{sta_owencpu,evt_wait, sta_sleep_int,action_callback},{sta_owencpu,evt_wait_unint, sta_sleep_unint,action_callback},{sta_owencpu,evt_wake_up, sta_owencpu,},{sta_owencpu,evt_wake, sta_owencpu,},};/*sleep_int*/
StateTransform stateTran_3={{sta_sleep_int,evt_fork, sta_sleep_int,},{sta_sleep_int,evt_sched, sta_sleep_int,},{sta_sleep_int,evt_wait, sta_sleep_int,},{sta_sleep_int,evt_wait_unint, sta_sleep_int,},{sta_sleep_int,evt_wake_up, sta_sleep_int,},{sta_sleep_int,evt_wake, sta_running,action_callback},};/*sleep_unint*/
StateTransform stateTran_4={{sta_sleep_unint,evt_fork, sta_sleep_unint,},{sta_sleep_unint,evt_sched, sta_sleep_unint,},{sta_sleep_unint,evt_wait, sta_sleep_unint,},{sta_sleep_unint,evt_wait_unint, sta_sleep_unint,},{sta_sleep_unint,evt_wake_up, sta_running,action_callback},{sta_sleep_unint,evt_wake, sta_sleep_unint,},};

實現event發(fa)生函數:

void event_happen(unsigned int event)
功(gong)能:
根據發生的event以及當前的進程state,找到對應的StateTransform 結構體,并調用do_action
void do_action(StateTransform *statTran)
功能:
根據結構體變量StateTransform,實現狀態遷移(yi),并調用對應的(de)回(hui)調函數。
#define STATETRANS(n) (stateTran_##n)
/*change state & call callback*/voiddo_action(StateTransform *statTran)
{if( == statTran)
{perror("statTran is \n");
return;
}//狀態遷移globalState = statTran->nextState;if(statTran->action != )
{//調用回調函數statTran->action((void*)statTran);}else{
printf("invalid event,state not change\n");
}}voidevent_happen(unsigned int event)
{switch(globalState){case sta_origin:do_action(&STATETRANS(0)[event]);
break;
case sta_running:do_action(&STATETRANS(1)[event]);
break;
case sta_owencpu:do_action(&STATETRANS(2)[event]);
break;
case sta_sleep_int:do_action(&STATETRANS(3)[event]);
break;
case sta_sleep_unint:do_action(&STATETRANS(4)[event]);
break;
default:printf("state is invalid\n");
break;
}}

測試程序:功能:

  1. 初始(shi)化狀態機(ji)的初始(shi)狀態為(wei)sta_origin;

  2. 創建子線程(cheng),每隔一秒鐘顯(xian)示當(dang)前(qian)進程(cheng)狀態(tai);

  3. 事件發生順序為:evt_fork-->evt_sched-->evt_sched-->evt_wait-->evt_wake。

讀者可以跟(gen)自己的需要,修(xiu)改事件發生順序,觀(guan)察狀(zhuang)態的變化。

main.c

/*顯示(shi)當前狀態*/
void *show_stat(void *arg)
{int len;
char buf[64]={0};
while(1)
{sleep(1);
printf("cur stat:%s\n",statename[globalState]);
}}voidmain(void)
{init_machine;//創(chuang)建子(zi)線程(cheng),子(zi)線程(cheng)主要用(yong)于顯(xian)示當前狀態
pthread_create(&pid, ,show_stat, );
sleep(5);
event_happen(evt_fork);
sleep(5);
event_happen(evt_sched);
sleep(5);
event_happen(evt_sched);
sleep(5);
event_happen(evt_wait);
sleep(5);
event_happen(evt_wake);
}

運行結果:

什么是狀態機?用C語言實現進程5狀態模型

由結果可知:

evt_fork-->evt_sched-->evt_sched-->evt_wait-->evt_wake

該(gai)事件發生序列對應的狀態遷移(yi)順序為:

origen-->running-->owencpu-->owencpu-->sleep_int-->running
在線客服(fu)
客服電話
  • 0755-23712116
  • 13310869691