IO多路复用与select函数原理

  同时监听标准输入和管道,避免陷入读、写、报错的阻塞态。select函数参数里面有传入读集合、写集合以及error集合,会将对应的文件描述符存入对应的集合中(fd_set数据类型)。

 

 

 

   fd是文件描述符,对应内核态文件索引数组的下标。


#include <homeworkhead.h>
int main(int argc,char* argv[]){
    // ./chat1 1.pipe 2.pipe
    ARGS_CHECK(argc,3);
    int fdr = open(argv[1],O_RDONLY);//只读管道1
    ERROR_CHECK(fdr,-1,"open fdr");
    int fdw = open(argv[2],O_WRONLY);//只写管道2
    ERROR_CHECK(fdw,-1,"open fdw");
    puts("pipe established!");
    char buf[2048]={0};
    fd_set rdset;//监听读集合
    struct timeval timeout;
    struct stat timrrecord;//记录文件状态
   
    while (1)//开始死循环通信直到一方主动读EOF
    {
        FD_ZERO(&rdset);//读集合清零
        FD_SET(fdr,&rdset);//将读管道加入监听
        FD_SET(STDIN_FILENO,&rdset);//将标准输入加入监听
        timeout.tv_sec=60;//1分钟不通信主动断开聊天
        timeout.tv_usec=0;
        //肯定fdr最大,因为标准输入是0
        int sret = select(fdr+1,&rdset,NULL,NULL,&timeout);
        if(sret==0){
            printf("timeout!\n");
            break;
        }
        time_t now ;
        struct tm *tm_now ;
        time(&now) ;
        tm_now = localtime(&now) ;//get time
 
        //轮询
        if(FD_ISSET(fdr,&rdset)){
            memset(buf,0,sizeof(buf));
            read(fdr,buf,sizeof(buf));
            printf("%d:%d:%d  ",tm_now->tm_hour,
                tm_now->tm_min,tm_now->tm_sec);
            puts(buf);
        }
        if(FD_ISSET(STDIN_FILENO,&rdset)){
            memset(buf,0,sizeof(buf));
            read(STDIN_FILENO,buf,sizeof(buf));
            write(fdw,buf,strlen(buf)-1);
        }
    }
   
    return 0;
}
 
 
 
posted @ 2022-02-27 15:48  晓风霜度-  阅读(156)  评论(0)    收藏  举报