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 ,在两个字符终端间分别输入数据,会在相对的字符终端显示数据。