zoukankan      html  css  js  c++  java
  • 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
    ", 5);
    
        fd2 = open(TTY2 , O_RDWR | O_NONBLOCK);
        if(fd2 < 0)
        {
            perror("open()");
            exit(1);
        }
        write(fd2 , "TTY2
    ", 5);
        //修改文件状态
        relay(fd1 , fd2);
    
        close(fd2);
        close(fd1);
        exit(0);
    }

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

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

  • 相关阅读:
    JVM常用参数设置
    Jstat在分析java的内存GC时的应用
    jstack来分析linux服务器上Java应用服务性能异常
    linux 远程连接服务器ftp命令整理
    LR11中webservice协议的性能测试应用
    Windbg在.net性能问题排查hang情况的应用思路
    Windbg基本命令应用总结
    LR11直接对数据库访问操作方法在性能测试中的应用总结
    BenchmarkSQL v5.0测试达梦数据库
    SSH登录时间久,登录后报错:'abrt-cli status' timed out
  • 原文地址:https://www.cnblogs.com/muzihuan/p/5383227.html
Copyright © 2011-2022 走看看