C语言:高级IO

非阻塞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;
            }
     
评论 2
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

only-lucky

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值