Programing

상태 머신 튜토리얼

lottogame 2020. 11. 7. 08:53
반응형

상태 머신 튜토리얼


상태 머신을 개발하기위한 인터넷의 좋은 튜토리얼을 아는 사람이 있는지 궁금합니다. 아니면 전자 책?

상태 머신 작업을 시작하고 있으며 시작하려면 일반적인 것이 필요합니다.


함수 포인터를 사용하는 경우 상태 머신은 C에서 매우 간단합니다.

기본적으로 2 개의 배열이 필요합니다. 하나는 상태 함수 포인터 용이고 다른 하나는 상태 전환 규칙 용입니다. 모든 상태 함수는 코드를 반환하고 상태 별 상태 전환 테이블을 조회하고 코드를 반환하여 다음 상태를 찾은 다음 실행합니다.

int entry_state(void);
int foo_state(void);
int bar_state(void);
int exit_state(void);

/* array and enum below must be in sync! */
int (* state[])(void) = { entry_state, foo_state, bar_state, exit_state};
enum state_codes { entry, foo, bar, end};

enum ret_codes { ok, fail, repeat};
struct transition {
    enum state_codes src_state;
    enum ret_codes   ret_code;
    enum state_codes dst_state;
};
/* transitions from end state aren't needed */
struct transition state_transitions[] = {
    {entry, ok,     foo},
    {entry, fail,   end},
    {foo,   ok,     bar},
    {foo,   fail,   end},
    {foo,   repeat, foo},
    {bar,   ok,     end},
    {bar,   fail,   end},
    {bar,   repeat, foo}};

#define EXIT_STATE end
#define ENTRY_STATE entry

int main(int argc, char *argv[]) {
    enum state_codes cur_state = ENTRY_STATE;
    enum ret_codes rc;
    int (* state_fun)(void);

    for (;;) {
        state_fun = state[cur_state];
        rc = state_fun();
        if (EXIT_STATE == cur_state)
            break;
        cur_state = lookup_transitions(cur_state, rc);
    }

    return EXIT_SUCCESS;
}

lookup_transitions()사소하기 때문에 기능을 두지 않습니다 .

이것이 제가 몇 년 동안 상태 머신을하는 방식입니다.


나는 거대한 switch보다 함수 포인터를 사용하는 것을 선호 하지만 qrdl의 대답 과는 달리 일반적으로 명시 적 반환 코드 나 전환 테이블을 사용하지 않습니다.

또한 대부분의 경우 추가 데이터를 전달하는 메커니즘이 필요합니다. 다음은 상태 머신의 예입니다.

#include <stdio.h>

struct state;
typedef void state_fn(struct state *);

struct state
{
    state_fn * next;
    int i; // data
};

state_fn foo, bar;

void foo(struct state * state)
{
    printf("%s %i\n", __func__, ++state->i);
    state->next = bar;
}

void bar(struct state * state)
{
    printf("%s %i\n", __func__, ++state->i);
    state->next = state->i < 10 ? foo : 0;
}

int main(void)
{
    struct state state = { foo, 0 };
    while(state.next) state.next(&state);
}

상태 머신은 본질적으로 설명하거나 사용하기 위해 튜토리얼이 필요한 것이 아닙니다. 내가 제안하는 것은 데이터를 살펴보고 파싱해야하는 방법입니다.

For example, I had to parse the data protocol for a Near Space balloon flight computer, it stored data on the SD card in a specific format (binary) which needed to be parsed out into a comma seperated file. Using a state machine for this makes the most sense because depending on what the next bit of information is we need to change what we are parsing.

The code is written using C++, and is available as ParseFCU. As you can see, it first detects what version we are parsing, and from there it enters two different state machines.

It enters the state machine in a known-good state, at that point we start parsing and depending on what characters we encounter we either move on to the next state, or go back to a previous state. This basically allows the code to self-adapt to the way the data is stored and whether or not certain data exists at all even.

In my example, the GPS string is not a requirement for the flight computer to log, so processing of the GPS string may be skipped over if the ending bytes for that single log write is found.

State machines are simple to write, and in general I follow the rule that it should flow. Input going through the system should flow with certain ease from state to state.


Unfortunately, most of the articles on state machines are written for C++ or other languages that have direct support for polymorphism as it's nice to model the states in an FSM implementation as classes that derive from an abstract state class.

However, it's pretty easy to implement state machines in C using either switch statements to dispatch events to states (for simple FSMs, they pretty much code right up) or using tables to map events to state transitions.

There are a couple of simple, but decent articles on a basic framework for state machines in C here:

Edit: Site "under maintenance", web archive links:

switch statement-based state machines often use a set of macros to 'hide' the mechanics of the switch statement (or use a set of if/then/else statements instead of a switch) and make what amounts to a "FSM language" for describing the state machine in C source. I personally prefer the table-based approach, but these certainly have merit, are widely used, and can be effective especially for simpler FSMs.

One such framework is outlined by Steve Rabin in "Game Programming Gems" Chapter 3.0 (Designing a General Robust AI Engine).

A similar set of macros is discussed here:

If you're also interested in C++ state machine implementations there's a lot more that can be found. I'll post pointers if you're interested.


Real-Time Object-Oriented Modeling was fantastic (published in 1994 and now selling for as little as 81 cents, plus $3.99 shipping).


This is all you need to know.

int state = 0;
while (state < 3)
{
    switch (state)
    {
        case 0:
            // Do State 0 Stuff
            if (should_go_to_next_state)
            {
                state++;
            }
            break;
        case 1:
            // Do State 1 Stuff    
            if (should_go_back) 
            {
                state--;
            }    
            else if (should_go_to_next_state) 
            {
                state++;
            }
            break;
        case 2:
            // Do State 2 Stuff    
            if (should_go_back_two) 
            {
                state -= 2;
            }    
            else if (should_go_to_next_state) 
            {
                state++;
            }
            break;
        default:
            break;
    }
}

There is a lot of lesson to learn handcrafting state machines in C, but let me also suggest Ragel state machine compiler:

http://www.complang.org/ragel/

It has quite simple way of defining state machines and then you can generate graphs, generate code in different styles (table-driven, goto-driven), analyze that code if you want to, etc. And it's powerful, can be used in production code for various protocols.


State machines can be very complex for a complex problem. They are also subject to unexpected bugs. They can turn into a nightmare if someone runs into a bug or needs to change the logic in the future. They are also difficult to follow and debug without the state diagram. Structured programming is much better (for example you would probably not use a state machine at mainline level). You can use structured programming even in interrupt context (which is where state machines are usually used). See this article "Macros to simulate multi-tasking/blocking code at interrupt level" found at codeproject.com.

참고URL : https://stackoverflow.com/questions/1371460/state-machines-tutorials

반응형