linux高编IO-------有限状态机编程原理(mycpy)

有限状态机:负责解决复杂流程

简单流程:如果一个程序的自然流程是结构化的

复杂流程:如果一个程序的自然流程不是结构化的

网络协议:一般不是简单流程

 

=================================================================================================

用有限状态机思想实现mycpy

==============================================================================================

范例:

/**********************
 *有限状态机实现mycpy
 * *******************/
#include <stdio.h>
#include <stdlib.h>
#include <sys/types.h>
#include <sys/stat.h>
#include <fcntl.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 buf[BUFSIZE];//存储读取的数据
    char *strerr ;//出错原因
};



//有限状态机驱动
static void fsm_driver(struct fsm_st *fsm)
{
    int ret ;
    switch (fsm->state)
    {
        //1.读
        case STATE_R:
            fsm->len = read(fsm->sfd , fsm->buf ,BUFSIZE);
            //1.1没有数据
            if(fsm->len == 0)
                fsm->state = STATE_T ;
            //1.2读失败
            else if(fsm->len < 0)
            {
                //判断真错假错
                if(errno == EAGAIN)
                    fsm->state = STATE_R ;
                else
                {
                    fsm->strerr = "read()";
                    fsm->state = STATE_EX ;
                }
            }
            //1.3读成功后,推动写
            else
            {
                fsm->pos = 0;
                fsm->state = STATE_W;
            }
            break ;
        //2.写
        case STATE_W:
            ret = write(fsm->dfd , fsm->buf+fsm->pos , fsm->len);
            //2.1写失败
            if(ret < 0)
            {   //判断真错假错
                if(errno == EAGAIN)
                    fsm->state = STATE_W ;
                else
                {
                    fsm->strerr = "write()";
                    fsm->state = STATE_EX ;
                }
            }
            //2.2写成功
            else
            {
                fsm->pos += ret ;
                fsm->len -= ret ;
                if(fsm->len == 0)
                    fsm->state = STATE_R ;
                else
                    fsm->state = STATE_W ;

            }
            break ;
        //3.异常
        case STATE_EX:
            perror(fsm->strerr);
            fsm->state = STATE_T ;
            break ;
        //4.终止
        case STATE_T :

            break;
        default :
            abort();
            break;
    }
}

//修改设备状态(都为NONBLOCK方式),并为每个设备初始化有限状态机
static void relay(int fd1 ,int fd2)
{
    int fd1_save , fd2_save ;
    struct fsm_st fsm12,fsm21;
    //1.保存设备初始状态
    fd1_save = fcntl(fd1,F_GETFL);
    //2.设置设备的NONBLOCK状态
    fcntl(fd1 ,F_SETFL ,fd1_save | O_NONBLOCK);

    fd2_save = fcntl(fd2 , F_GETFL);
    fcntl(fd2,F_SETFL,fd2_save | O_NONBLOCK);
    //3.初始化有限状态机
    fsm12.state = STATE_R ;
    fsm12.sfd = fd1 ;
    fsm12.dfd = fd2 ;

    fsm21.state = STATE_R ;
    fsm21.sfd = fd2 ;
    fsm21.dfd = fd1 ;
    //4.start推动状态机运行
    while(fsm12.state != STATE_T || fsm21.state != STATE_T)
    {
        fsm_driver(&fsm12);
        fsm_driver(&fsm21);

    }
    //5.设备状态恢复
    fcntl(fd1 , F_SETFL , fd1_save);
    fcntl(fd2 , F_SETFL , fd2_save);


}
int main()
{
    int fd1, fd2 ;
    //用户可以使用BLOCK方式或者NONBLOCK方式打开文件
    fd1 = open(TTY1,O_RDWR);
    if(fd1 < 0 )
    {
        perror("open()");
        exit(1);
    }
    write(fd1 , "TTY1\n", 5);

    fd2 = open(TTY2 , O_RDWR | O_NONBLOCK);
    if(fd2 < 0)
    {
        perror("open()");
        exit(1);
    }
    write(fd2 , "TTY2\n", 5);
    //修改文件状态
    relay(fd1 , fd2);

    close(fd2);
    close(fd1);
    exit(0);
}

 

运行结果:在终端运行可执行程序

ctl+alt+F11 和ctl+alt+F12 ,在两个字符终端间分别输入数据,会在相对的字符终端显示数据。

 

posted @ 2016-04-12 16:31  muzihuan  阅读(913)  评论(0编辑  收藏  举报