非阻塞IO和阻塞IO
man手册7章是在将机制。
------- EINTR:(error interrupt)是阻塞的系统调用,动作非常的慢,这个过程被信号打断了,但并不是操作失败,故是个假错。
----------EAGAIN.(error again) 是非堵塞的调用,表示,尝试去做了,但是现在没有数据,并不是真的出错了(并不是当前系统调用函数的问题)。
有限状态机编程
简单流程:一个程序的自然流程是结构化的就叫简单流程。
复杂流程:一个程序的自然流程是非结构化的就叫复杂流程。
relay.c
#include <stdlib.h>
#include <stdio.h>
#include <unistd.h>
#include <string.h>
#include <errno.h>
#include <sys/types.h>
#include <sys/stat.h>
#include <fcntl.h>
#define TTY1 "/dev/tty11"
#define TTY2 "/dev/tty12"
#define BUFSIZE 1024
enum
{
STATE_R = 1, //读态
STATE_W = 2, // 写态
STATE_Ex, // 异常态
STATE_T //结束态
};
struct fsm_st
{
int state;
int sfd;
int dfd;
char buf[BUFSIZE];
int len;
int pos;
char *errstr;
};
void fsm_driver(struct fsm_st*fsm)
{
int ret;
switch(fsm->state)
{
case STATE_R:
fsm->len = read(fsm->sfd,fsm->buf,BUFSIZE);
if(fsm->len ==0)
fsm->state = STATE_T;
else if(fsm->len < 0)
{
if(errno == EAGAIN) //假错
fsm->state = STATE_R;
else
{
fsm->errstr = "read()";
fsm->state = STATE_Ex;
}
}
else
{
fsm->pos = 0;
fsm->state = STATE_W;
}
break;
case STATE_W:
ret = write(fsm->dfd,fsm->buf+fsm->pos,fsm->len);
if(ret<0)
{
if(errno == EAGAIN)
fsm->state = STATE_W;
else
{
fsm->errstr = "write()";
fsm->state = STATE_Ex;
}
}
else
{
fsm->len -= ret;
fsm->pos += ret;
if(fsm->len ==0)
fsm->state = STATE_R;
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;
}
}
void relay(int fd1,int fd2)
{
int fd1_save,fd2_save;
struct fsm_st fsm12,fsm21;
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,"TTY1\n",5);
fd2 = open(TTY2,O_RDWR|O_NONBLOCK); //以非堵塞形式打开
write(fd2,"TTY2\n",5);
relay(fd1,fd2);
close(fd1);
close(fd2);
return 0;
}
在虚拟机中使用Ctrl+Alt+ F11 切换11终端设备。12同理。
可以使用dia工具进行绘图,类似于windows下的Visio。
非阻塞IO
man.c
#include <stdlib.h>
#include <stdio.h>
#include <unistd.h>
#include <string.h>
#include <errno.h>
#include <sys/types.h>
#include <sys/stat.h>
#include <fcntl.h>
#include "relayer.h"
#define TTY1 "/dev/tty11"
#define TTY2 "/dev/tty12"
#define TTY3 "/dev/tty10"
#define TTY4 "/dev/tty9"
#define BUFSIZE 1024
int main()
{
int fd1,fd2;
int job1;
fd1 = open(TTY1,O_RDWR);
if(fd1< 0)
{
perror("open()");
exit(1);
}
write(fd1,"TTY1\n",5);
fd2 = open(TTY2,O_RDWR|O_NONBLOCK); //以非堵塞形式打开
write(fd2,"TTY2\n",5);
job1 = rel_addjob(fd1,fd2);
if(job1<0)
{
fprintf(stderr,"rel_addjob():%s\n",strerror(-job1));
exit(1);
}
int fd3,fd4;
int job2;
fd3 = open(TTY3,O_RDWR);
write(fd3,"TTY3\n",5);
fd4 = open(TTY3,O_RDWR);
write(fd4,"TTY4\n",5);
job2 =rel_addjob(fd3,fd4);
while(1);
close(fd1);
close(fd2);
close(fd3);
close(fd4);
return 0;
}
relayer.c
#include <stdlib.h>
#include <stdio.h>
#include <unistd.h>
#include <string.h>
#include <errno.h>
#include <sys/types.h>
#include <sys/stat.h>
#include <fcntl.h>
#include <pthread.h>
#include "relayer.h"
#define TTY1 "/dev/tty11"
#define TTY2 "/dev/tty12"
#define BUFSIZE 1024
static struct rel_job_st* rel_job[REL_JOBMAX];
static pthread_mutex_t mut_rel_job = PTHREAD_MUTEX_INITIALIZER;
static pthread_once_t init_once = PTHREAD_ONCE_INIT;
enum
{
STATE_R = 1, //读态
STATE_W = 2, // 写态
STATE_Ex, // 异常态
STATE_T //结束态
};
struct rel_fsm_st
{
int state;
int sfd;
int dfd;
char buf[BUFSIZE];
int len;
int pos;
char *errstr;
int64_t count;
};
struct rel_job_st
{
int job_state;
int fd1;
int fd2;
struct rel_fsm_st fsm12,fsm21;
int fd1_save,fd2_save;
// struct timerval start,end;
};
void fsm_driver(struct rel_fsm_st*fsm)
{
int ret;
switch(fsm->state)
{
case STATE_R:
fsm->len = read(fsm->sfd,fsm->buf,BUFSIZE);
if(fsm->len ==0)
fsm->state = STATE_T;
else if(fsm->len < 0)
{
if(errno == EAGAIN) //假错
fsm->state = STATE_R;
else
{
fsm->errstr = "read()";
fsm->state = STATE_Ex;
}
}
else
{
fsm->pos = 0;
fsm->state = STATE_W;
}
break;
case STATE_W:
ret = write(fsm->dfd,fsm->buf+fsm->pos,fsm->len);
if(ret<0)
{
if(errno == EAGAIN)
fsm->state = STATE_W;
else
{
fsm->errstr = "write()";
fsm->state = STATE_Ex;
}
}
else
{
fsm->len -= ret;
fsm->pos += ret;
if(fsm->len ==0)
fsm->state = STATE_R;
else
fsm->state = STATE_W;
}