LinuxC应用开发学习笔记(十三)—高级I\O

高级I\O

非阻塞IO – 阻塞 IO
补充:有限状态机编程

有限状态机
#include <stdio.h>
#include <stdlib.h>
#include <sys/types.h>
#include <sys/stat.h>
#include <fcntl.h>
#include <unistd.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 * errstr;
    char buf[BUFSIZE];
};

static 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 = "read()";
                fsm->state =STATE_Ex;
            }
                
        }
        else
        {
            fsm->pos += ret;

            fsm->len -= 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;
    }

}
 
static 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);
    if (fd2<0)
    {
        perror("open()");
        exit(1);
    }

    write(fd2,"TTY2\n",5);

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

简单流程:自然流程是结构化的

复杂流程:自然流程不是结构化的

1、非阻塞IO

中继引擎实现实例

.h文件

#ifndef RELAYER_H__
#define RELAYER_H__
#include <stdio.h>
#include <stdlib.h>
#include <string.h>

#define REL_JOBMAX 10000 

enum
{
    STATE_RUNNING=1,
    STATE_CANCELED,
    STATE_OVER

};



struct rel_stat_st
{
    int state;
    int fd1;
    int fd2;
    int64_t count12,count21;
    //struct timerval start end;
};


int rel_addjob(int fd,int fd2);
/*
*  return >=0  成功 返回当前任务ID
*          == -EINVAL 失败 参数非法
*          == -ENOSPC 失败 任务数组满
*          == -ENNMEM 失败 内存分配有误
*            
*/

int rel_canceljob(int fd);
/*
*  return  == 0  成功 制定任务成功取消
*          == -EINVAL 失败 参数非法
*          == -EBUSY  失败 任务早已被取消         
*/

int rel_waitjob(int fd,struct rel_stat_st *);
/*
*  return  == 0  成功 指定任务已终止并返回状态
*          == -EINVAL 失败 参数非法
*          == -EBUSY  失败 任务早已被取消         
*/

int rel_statjob(int fd,struct rel_stat_st *);
/*
*  return  == 0  成功  指定状态已经返回
*          == -EINVAL 失败 参数非法
*          == -EBUSY  失败 任务早已被取消         
*/

#endif // !RELAYER_H__

relayer.c文件

#include "relayer.h"
#include <stdio.h>
#include <stdlib.h>
#include <sys/types.h>
#include <sys/stat.h>
#include <fcntl.h>
#include <unistd.h>
#include <errno.h>
#include <pthread.h>

#define  TTY1 "/dev/tty11"
#define  TTY2 "/dev/tty12"

#define BUFSIZE 1024 

enum
{
    STATE_R = 1,
    STATE_W,
    /*异常终止态*/
    STATE_Ex,
    STATE_T
};

struct rel_fsm_st
{
    int state;
    int sfd;
    int dfd;
    int len;
    int pos;
    char * errstr;
    char buf[BUFSIZE];
    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;
};

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;

static 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 = "read()";
                fsm->state =STATE_Ex;
            }
                
        }
        else
        {
            fsm->pos += ret;

            fsm->len -= 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;
    }

}

static void *thr_relayer(void *p)
{
    while (1)
    {
    pthread_mutex_lock(&mut_rel_job);
        for (int i = 0; i < REL_JOBMAX; i++)
        {
            if (rel_job[i]!=NULL)
            {
                if (rel_job[i]->job_state == STATE_RUNNING)
                {
                    fsm_driver(&rel_job[i]->fsm12);
                    fsm_driver(&rel_job[i]->fsm21);
                    if(rel_job[i]->fsm12.state == STATE_T&&rel_job[i]->fsm21.state == STATE_T)
                    {
                        rel_job[i]->job_state = STATE_OVER;
                    }  
                }   
            }
        }
        pthread_mutex_unlock(&mut_rel_job);
    }
}

//static module_unload(void)
static void  module_load(void)
{
    int err = 0;
    pthread_t tid_relayer;
    err = pthread_create(&tid_relayer,NULL,thr_relayer,NULL);
    if (err)
    {
        fprintf(stderr,"pthread_create():%s\n",strerror(err));
        exit(1);
    }  
}


static int get_free_pos_unlocked()
{
    int i;
    for (i = 0; i < REL_JOBMAX; i++)
    {
        if (rel_job[i]==NULL) 
            return i;
    }
    return -1;
    
}


int rel_addjob(int fd1,int fd2)
{
    struct rel_job_st *me;
    /*动态模块的一次性初始化*/
    pthread_once(&init_once,module_load);

    int pos = 0;
    me = malloc(sizeof(*me));
    if (me == NULL)
       return -ENOMEM;
    me->fd1 = fd1;
    me->fd2 = fd2;
    me->job_state = STATE_RUNNING;



    /*保存状态,确保fd1和fd2都是非阻塞打开的*/
    me->fd1_save = fcntl(me->fd1,F_GETFL);
    fcntl(me->fd1,F_SETFL,me->fd1_save|O_NONBLOCK);
    
    me->fd2_save = fcntl(me->fd2,F_GETFL);
    fcntl(me->fd2,F_SETFL,me->fd2_save|O_NONBLOCK);
    

    me->fsm12.sfd = me->fd1;
    me->fsm12.dfd = me->fd2;
    me->fsm12.state = STATE_R;

    me->fsm21.sfd = me->fd2;
    me->fsm21.dfd = me->fd1;
    me->fsm21.state = STATE_R;

    pthread_mutex_lock(&mut_rel_job);
    get_free_pos_unlocked();
    if (pos < 0)
    {
        pthread_mutex_unlock(&mut_rel_job);
        fcntl(me->fd1,F_SETFL,me->fd1_save);
        fcntl(me->fd2,F_SETFL,me->fd2_save);
        free(me);
        return -ENOSPC;
    }

    rel_job[pos] = me;
    
    pthread_mutex_unlock(&mut_rel_job);
    
    return pos;
}
#if 0
int re_canceljob(int fd);


int re_waitjob(int fd,struct rel_stat_st *);


int re_statjob(int fd,struct rel_stat_st *);
#endif

main.c文件

#include <stdio.h>
#include <stdlib.h>
#include <sys/types.h>
#include <sys/stat.h>
#include <fcntl.h>
#include <unistd.h>
#include <errno.h>
#include <string.h>
#include "relayer.h"

#define  TTY1 "/dev/tty11"
#define  TTY2 "/dev/tty12"
#define  TTY3 "/dev/tty10"
#define  TTY4 "/dev/tty9"


int main()
{
    int fd1,fd2,fd3,fd4;
    int job1,job2;

    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);
    job1 = rel_addjob(fd1,fd2);
    if (job1 < 0)
    {
        fprintf(stderr,"rel_addjob():%s\n",strerror(-job1));
        exit(1);
    }
    
    fd3 = open(TTY3,O_RDWR);
    if (fd3<0)
    {
        perror("open()");
        exit(1);
    }
    write(fd3,"TTY3\n",5);

    fd4 = open(TTY4,O_RDWR);
    if (fd4<0)
    {
        perror("open()");
        exit(1);
    }
    write(fd3,"TTY4\n",5);

    job2 = rel_addjob(fd3,fd4);
    if (job2<0)
    {
        fprintf(stderr,"rel_addjob():%s\n",strerror(-job2));
        exit(1);
    }
    while (1)
        pause();    

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

2、IO多路转接

select();//移植性非常好,以事件为单位组织文件描述符。

select()示例
#include <stdio.h>
#include <stdlib.h>
#include <sys/types.h>
#include <sys/stat.h>
#include <sys/select.h>
#include <fcntl.h>
#include <unistd.h>
#include <errno.h>

#define  TTY1 "/dev/tty11"
#define  TTY2 "/dev/tty12"

#define BUFSIZE 1024 

enum
{
    STATE_R = 1,
    STATE_W,
    /*异常终止态*/
    STATE_AUTO,
    STATE_Ex,
    STATE_T
};

struct fsm_st
{
    int state;
    int sfd;
    int dfd;
    int len;
    int pos;
    char * errstr;
    char buf[BUFSIZE];
};

static 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 = "read()";
                fsm->state =STATE_Ex;
            }
                
        }
        else
        {
            fsm->pos += ret;

            fsm->len -= 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;
    }

}
 
static int max(int a,int b)
{
    if (a>b)
        return a;
    return b;
}

static void relay(int fd1,int fd2)
{
    int fd1_save,fd2_save;
    struct fsm_st fsm12,fsm21;
    
    fd_set rset,wset;

    /*保证两个文件是以非阻塞方式实现*/
    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 )
    {
        //布置监视任务
        //读集设置为空集
        FD_ZERO(&rset);
        FD_ZERO(&wset);
        if (fsm12.state == STATE_R)
            FD_SET(fsm12.sfd,&rset);
        if (fsm12.state == STATE_W)
            FD_SET(fsm12.sfd,&wset); 

        if (fsm21.state == STATE_R)
            FD_SET(fsm21.sfd,&rset);
        if (fsm21.state == STATE_W)
            FD_SET(fsm21.sfd,&wset);      

        //监视
        if(fsm12.state<STATE_AUTO||fsm21.state<STATE_AUTO)
        {
            if (select(max(fd1,fd2)+1,&rset,&wset,NULL,NULL)<0)
            {
                if (errno == EINTR)
                    continue;
                perror("select()");
                exit(1);
            }

        }
        

        //查看监视结果

        if(FD_ISSET(fd1,&rset)||FD_ISSET(fd2,&wset)||fsm12.state > STATE_AUTO)
            fsm_driver(&fsm12);
        if(FD_ISSET(fd2,&rset)||FD_ISSET(fd1,&wset)||fsm12.state > STATE_AUTO)
            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);
    if (fd2<0)
    {
        perror("open()");
        exit(1);
    }

    write(fd2,"TTY2\n",5);

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

poll();//以文件描述符为单位来组织事件,也可以移植。

poll示例
#include <stdio.h>
#include <stdlib.h>
#include <sys/types.h>
#include <sys/stat.h>
#include <sys/select.h>
#include <fcntl.h>
#include <unistd.h>
#include <errno.h>
#include <poll.h>

#define  TTY1 "/dev/tty11"
#define  TTY2 "/dev/tty12"

#define BUFSIZE 1024 

enum
{
    STATE_R = 1,
    STATE_W,
    /*异常终止态*/
    STATE_AUTO,
    STATE_Ex,
    STATE_T
};

struct fsm_st
{
    int state;
    int sfd;
    int dfd;
    int len;
    int pos;
    char * errstr;
    char buf[BUFSIZE];
};

static 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 = "read()";
                fsm->state =STATE_Ex;
            }
                
        }
        else
        {
            fsm->pos += ret;

            fsm->len -= 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;
    }

}
 
static int max(int a,int b)
{
    if (a>b)
        return a;
    return b;
}

static void relay(int fd1,int fd2)
{
    int fd1_save,fd2_save;
    struct fsm_st fsm12,fsm21;
    
    struct pollfd pfd[2];

    /*保证两个文件是以非阻塞方式实现*/
    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;

    pfd[0].fd = fd1;
    pfd[1].fd = fd2;
    while (fsm12.state != STATE_T ||fsm21.state != STATE_T )
    {
        //布置监视任务
        //读集设置为空集
        pfd[0].events = 0;
        if (fsm12.state == STATE_R)
            pfd[0].events |= POLLIN;
        if (fsm21.state == STATE_W)
            pfd[0].events |= POLLOUT;

        pfd[1].events = 0;
        if (fsm21.state == STATE_R)
            pfd[1].events |= POLLIN;
        if (fsm12.state == STATE_W)
            pfd[1].events |= POLLOUT;

        
        

        //监视
        if(fsm12.state<STATE_AUTO||fsm21.state<STATE_AUTO)
        {
            while(poll(pfd,2,-1)<0)
            {
                if (errno == EINTR)
                    continue;
                perror("poll()");
                exit(1);
            }

        }
        

        //查看监视结果

        if(pfd[0].revents&POLLIN|| pfd[1].revents&POLLOUT||fsm12.state > STATE_AUTO)
            fsm_driver(&fsm12);
        if(pfd[1].revents&POLLIN|| pfd[0].revents&POLLOUT||fsm12.state > STATE_AUTO)
            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);
    if (fd2<0)
    {
        perror("open()");
        exit(1);
    }

    write(fd2,"TTY2\n",5);

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

epoll();//linux的方言,无法移植。

epoll示例
#include <stdio.h>
#include <stdlib.h>
#include <sys/types.h>
#include <sys/stat.h>
#include <sys/select.h>
#include <fcntl.h>
#include <unistd.h>
#include <errno.h>
#include <sys/epoll.h>

#define  TTY1 "/dev/tty11"
#define  TTY2 "/dev/tty12"

#define BUFSIZE 1024 

enum
{
    STATE_R = 1,
    STATE_W,
    /*异常终止态*/
    STATE_AUTO,
    STATE_Ex,
    STATE_T
};

struct fsm_st
{
    int state;
    int sfd;
    int dfd;
    int len;
    int pos;
    char * errstr;
    char buf[BUFSIZE];
};

static 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 = "read()";
                fsm->state =STATE_Ex;
            }
                
        }
        else
        {
            fsm->pos += ret;

            fsm->len -= 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;
    }

}
 
static int max(int a,int b)
{
    if (a>b)
        return a;
    return b;
}

static void relay(int fd1,int fd2)
{
    int fd1_save,fd2_save;
    struct fsm_st fsm12,fsm21;
    struct epoll_event ev;
    int epfd;

    /*保证两个文件是以非阻塞方式实现*/
    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;

    epfd = epoll_create(10);
    if (epfd < 0 )
    {
        perror("epoll_create()");
        exit(1);
    }
    
    ev.events = 0;
    ev.data.fd = fd1;
    epoll_ctl(epfd,EPOLL_CTL_ADD,fd1,&ev);
    

    ev.events = 0;
    ev.data.fd = fd2;
    epoll_ctl(epfd,EPOLL_CTL_ADD,fd2,&ev);
    

    while (fsm12.state != STATE_T ||fsm21.state != STATE_T )
    {
        //布置监视任务
        //读集设置为空集
        ev.data.fd =fd1;
        ev.events = 0;


        //epoll_ctl(epfd,EPOLL_CTL_MOD);

        if (fsm12.state == STATE_R)
            ev.events |= EPOLLIN;
          
        if (fsm21.state == STATE_W)
            ev.events |= EPOLLOUT;

        epoll_ctl(epfd,EPOLL_CTL_MOD,fd1,&ev);
           

        ev.data.fd =fd2;
        ev.events = 0;
        if (fsm21.state == STATE_R)
           ev.events |= EPOLLOUT;
        if (fsm12.state == STATE_W)
           ev.events |= EPOLLIN;
           

        //监视
        if(fsm12.state<STATE_AUTO||fsm21.state<STATE_AUTO)
        {
            while(epoll_wait(epfd,&ev,1,-1)<0)
            {
                if (errno == EINTR)
                    continue;
                perror("epoll_wait()");
                exit(1);
            }

        }
        

        //查看监视结果

        if(ev.data.fd == fd1 &&ev.events &EPOLLIN\
        ||ev.data.fd == fd2&&ev.events&EPOLLOUT\
        ||fsm12.state > STATE_AUTO)
            fsm_driver(&fsm12);
        if(ev.data.fd == fd2 &&ev.events &EPOLLIN\
        ||ev.data.fd == fd2&&ev.events&EPOLLOUT\
        ||fsm12.state > STATE_AUTO)
            fsm_driver(&fsm21);   
    }

    /*恢复之前的状态*/
    fcntl(fd1,F_SETFL,fd1_save);
    fcntl(fd2,F_SETFL,fd2_save);

    close(epfd);
     
}

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);
    if (fd2<0)
    {
        perror("open()");
        exit(1);
    }

    write(fd2,"TTY2\n",5);

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

3、其他读写函数

readv();//读写可以碎片化
writev();

readn();//unix的独家函数
writen();

4、存储映射IO

mmap() &&munmap()示例
#include <stdio.h>
#include <stdlib.h>
#include <sys/types.h>
#include <sys/stat.h>
#include <fcntl.h>
#include <unistd.h>
#include <errno.h>
#include <sys/mman.h>

int main(int argc,char **argv)
{

    int fd,count=0;
    /*获取文件字节长度的结构体*/
    struct stat statres;

    char* str;

    if(argc<2)
    {
        fprintf(stderr,"Usage...\n");
        exit(1);
    }

    fd = open(argv[1],O_RDONLY);
    if (fd<0)
    {
        perror("open()");
        exit(1);
    }
    
    if (fstat(fd,&statres)<0)
    {
        perror("fstat()");
        exit(1);
    }

    str = mmap(NULL,statres.st_size,PROT_READ,MAP_SHARED,fd,0);
    if (str == MAP_FAILED)
    {
        perror("mmap()");
        exit(1);
    }
    close(fd);

    for (int  i = 0; i < statres.st_size; i++)
    {
        if (str[i] == 'a')
        count++;
    }
    printf("%d\n",count);
    
    munmap(str,statres.st_size);

    exit(1);
}
共享内存的实现
#include <stdio.h>
#include <stdlib.h>
#include <sys/types.h>
#include <sys/stat.h>
#include <sys/wait.h>
#include <fcntl.h>
#include <unistd.h>
#include <errno.h>
#include <sys/mman.h>
#include <string.h>


#define MEMSIZE 1024 


int main(int argc,char **argv)
{
    char *ptr;

    pid_t pid;

    ptr =  mmap(NULL,MEMSIZE,PROT_READ|PROT_WRITE,MAP_SHARED|MAP_ANONYMOUS,-1,0);
    if (ptr == MAP_FAILED)
    {
        perror("mmap()");
        exit(1);
    }

    pid = fork();
    if (pid < 0)
    {
        perror("fork()");
        munmap(ptr,MEMSIZE);
        exit(1);
    }

    if (pid == 0)   //child write
    {
        strcpy(ptr,"hello!");
        munmap(ptr,MEMSIZE);    
        exit(0);
    }
    else            //parent read
    {
        wait(NULL);
        puts(ptr);
        munmap(ptr,MEMSIZE);    
        exit(0);
    }

}

5、文件锁

fcntl();
lockf();
flock();

lockf();示例 多进程取代多线程
#include <stdio.h>
#include <stdlib.h>
#include <unistd.h>
#include <errno.h>
#include <string.h>
#include <sys/types.h>
#include <sys/wait.h>

#define PROCNUM 20
#define FNAME "/tmp/out"  
#define LINESIZE 1024


char linebuf[LINESIZE];

static void  func_add(void)
{
    FILE *fp;
    int fd;

    fp = fopen(FNAME,"r+");
    if (fp == NULL)
    {
        perror("fopen()");
        exit(1);
    }
    
    fd = fileno(fp);

    lockf(fd,F_LOCK,0);
    fgets(linebuf,LINESIZE,fp);
    fseek(fp,0,SEEK_SET);
    sleep(1);
    fprintf(fp,"%d\n",atoi(linebuf)+1);
    fflush(fp);
    lockf(fd,F_ULOCK,0);
    fclose(fp);
}



int main()
{
    int err,i;
    pid_t pid;

    for ( i = 0; i < PROCNUM; i++)
    {
       fork();
       if (pid<0)
       {
           perror("fork()");
           exit(1);
       }
       if (pid == 0)
       {
           func_add();
           exit(0);
       }
   
    }

    for ( i = 0; i < PROCNUM; i++)
        wait(NULL);
    
    exit(0);
}

  • 1
    点赞
  • 2
    收藏
    觉得还不错? 一键收藏
  • 2
    评论
评论 2
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

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

余额充值