我是靠谱客的博主 敏感云朵,最近开发中收集的这篇文章主要介绍有限状态机的编程原理及编程实例,觉得挺不错的,现在分享给大家,希望可以做个参考。

概述

有限状态机

有限状态机解决的问题是复杂流程。
简单流程:自然流程是结构化的,按照人类顺序思维解决的问题。
复杂流程:自然流程不是结构化的,比如先前的MultiButton。

具体实例

在linux操作系统下实现终端设备界面相互切换。实现读取fd1的数据写入的fd2中,读取fd2的数据写入到fd1当中。

状态机简单示意图如下所示:
在这里插入图片描述

实验工程源码

#include <stdio.h>
#include <stdlib.h>
#include <sys/types.h>
#include <sys/stat.h>
#include <fcntl.h>
#include <unistd.h>
#include <errno.h>

#define  TTY1 "/dev/tty11"
#define  TTY2 "/dev/tty12"

#define BUFSIZE 1024 

/*********状态机状态枚举类型**********/
enum
{
	/*文件读状态*/
    STATE_R = 1,
   /*文件写状态*/
    STATE_W,
    /*异常终止态*/
    STATE_Ex,
    /*退出态*/
    STATE_T
};

/*********状态机结构体**********/
struct fsm_st
{
    /*状态机状态*/
    int state;
    /*源文件描述符*/
    int sfd;
    /*目标文件描述符*/
    int dfd;
    /*读取长度*/
    int len;
    /*位置*/
    int pos;
    /*报错信息*/
    char * errstr;
    /*buf缓冲区*/
    char buf[BUFSIZE];
};


/***********************启动状态机*****************/
static void fsm_driver(struct fsm_st*fsm)
{
    int ret;
    
    switch (fsm->state)
    {
    /*状态机读取*/
    case STATE_R:
    	/*读取到的源fd存储到buf中*/
        fsm->len = read(fsm->sfd,fsm->buf,BUFSIZE);
        /*如果读取0字节,退出状态机*/
        if (fsm->len == 0)
        fsm->state = STATE_T;
        /*如果读取<0字节,进行状态判断*/
        else if (fsm->len < 0)
        {
           /*如果读取<0字节,二次判断*/
            if (errno == EAGAIN)
                fsm->state =STATE_R;
            else
            {
            	/*宕机退出*/
                fsm->errstr = "read()";
                fsm->state =STATE_Ex;
            }    
        }
        else
        /*都没有报错,说明读取正常,则开始状态机写入*/
        {
        /*******初始化写入的位置为0***************/
            fsm->pos = 0;
            fsm->state =STATE_W;     
        }  
        break;
        
   /*状态机写入*/
    case STATE_W:
        /*写入读取到的数据len*/
        ret = write(fsm->dfd,fsm->buf+fsm->pos,fsm->len);
		/*写入读取到的数据<0*/
        if(ret < 0)
        {
        	/*假的错误*/
            if (errno == EAGAIN)
            	/*再次进入写入*/
                fsm->state = STATE_W;
            else 
            /*真正读取错误*/
            {
            	/*读取错误*/
                fsm->errstr = "read()";
                /*宕机退出*/
                fsm->state =STATE_Ex;
            }      
        }
        else
      /***************坚持写够len个字节数***************/
        {
           /*******从pos的位置继续向下写入字节***************/
            fsm->pos += ret;
            fsm->len -= ret;
            /*如果写入完成*/
            if(fsm->len == 0)
                /*返回读态*/
                fsm->state = STATE_R;
            /*否则返回写态,继续写够len个字节*/
            else 
                fsm->state = STATE_W;
        }
        break;
        
        /*宕机退出*/
    case STATE_Ex:
        perror(fsm->errstr);
        fsm->state = STATE_T;
        break;
        /*完整退出*/
    case STATE_T:
        /*do sth*/
        break;
    default:
        /*如果都不是以上任意一个状态,发送异常*/
        abort();
        break;
    }

}
 
 
static void relay(int fd1,int fd2)
{
    int fd1_save,fd2_save;
    /*读左写右和读右写左状态机*/
    struct fsm_st fsm12,fsm21;
    /***********************************************/
    /*保证两个文件是以非阻塞方式实现*/
    /*fcntl函数的作用是获取文件状态信息*/
    fd1_save = fcntl(fd1,F_GETFL); 
    fcntl(fd1,F_SETFL,fd1_save|O_NONBLOCK);
    
    fd2_save = fcntl(fd2,F_GETFL); 
    fcntl(fd2,F_SETFL,fd2_save|O_NONBLOCK);
    /***********************************************/

	/******************状态机初始化状态********* *****/
    fsm12.state = STATE_R;
    fsm12.sfd = fd1;
    fsm12.dfd = fd2;
    
    fsm21.state = STATE_R;
    fsm21.sfd = fd2;
    fsm21.dfd = fd1;
	/***********************************************/

	/*******************推动状态机*******************/
    while (fsm12.state != STATE_T ||fsm21.state != STATE_T )
    {
        fsm_driver(&fsm12);
        fsm_driver(&fsm21);   
    }
    /***********************************************/

    /******************恢复起始默认状态**************/
    fcntl(fd1,F_SETFL,fd1_save);
    fcntl(fd2,F_SETFL,fd2_save);     
    /***********************************************/
}

int main()
{
    int fd1,fd2;
	/*模拟用户打开设备*/
    fd1 = open(TTY1,O_RDWR);
    if (fd1<0)
    {
        perror("open()");
        exit(1);
    }

    write(fd1,"TTY1n",5);
	/*模拟用户打开设备,以非阻塞方式打开设备*/
    fd2 = open(TTY2,O_RDWR|O_NONBLOCK);
    if (fd2<0)
    {
        perror("open()");
        exit(1);
    }

    write(fd2,"TTY2n",5);
	/*中继引擎函数*/
    relay(fd1,fd2);
    close(fd2);
    close(fd1);
    
    exit(0);
}

最后

以上就是敏感云朵为你收集整理的有限状态机的编程原理及编程实例的全部内容,希望文章能够帮你解决有限状态机的编程原理及编程实例所遇到的程序开发问题。

如果觉得靠谱客网站的内容还不错,欢迎将靠谱客网站推荐给程序员好友。

本图文内容来源于网友提供,作为学习参考使用,或来自网络收集整理,版权属于原作者所有。
点赞(42)

评论列表共有 0 条评论

立即
投稿
返回
顶部