zoukankan      html  css  js  c++  java
  • Linux系统编程——I/O多路转接模型之select

    在这种模型下,如果请求的I/O操作阻塞,且它不是真正阻塞I/O,而是让其中的一个函数等待,在这期间,I/O还能进行其他操作。select()和poll()就属于这种模型。

    下面根据该模型一步步创建双管道聊天窗口机制:

    首先用mkfifo创建管道文件作为传入参数。

    Makefile:

    SRCS:=$(wildcard *.c)
    ELFS:=$(SRCS:%.c=%)
    all:$(ELFS)
    	@for i in $(ELFS);do gcc -o $${i} $${i}.c;done
    clean:
    	rm -rf $(ELFS)
    
    • 单管道:一端只读,一端只写,读端获取写端数据

    read_pipe.c

    #include <func.h>
    
    int main(int argc, char* argv[])
    {
    	ARGS_CHECK(argc, 2);
    	int fd = open(argv[1], O_RDONLY);
    	ERROR_CHECK(fd, -1, "open");
    	printf("read fd = %d
    ", fd);
    	char buf[128] = {0};
    	read(fd, buf, sizeof(buf));
    	printf("buf = %s
    ", buf);
    	return 0;
    }
    

    write_pipe.c

    #include <func.h>
    
    int main(int argc, char* argv[])
    {
    	ARGS_CHECK(argc, 2);
    	int fd = open(argv[1], O_WRONLY);
    	ERROR_CHECK(fd, -1, "open");
    	printf("write fd = %d
    ", fd);
    	sleep(3);
    	write(fd, "hello", 5);
    	return 0;
    }
    
    • 双管道模型

    read_pipe.c

    #include <func.h>
    
    int main(int argc, char* argv[])
    {
    	ARGS_CHECK(argc, 3);
    	int fdr = open(argv[1], O_RDONLY);
    	ERROR_CHECK(fdr, -1, "open");
    	int fdw = open(argv[2], O_WRONLY);
    	ERROR_CHECK(fdw, -1, "open");
    	printf("chat1 fdr = %d, fdw = %d
    ", fdr, fdw);
    	char buf[128] = {0};
    	read(fdr, buf, sizeof(buf));
    	printf("buf = %s
    ", buf);
    	write(fdw, "I am chat1",10);
    	return 0;
    }
    

    write_pipe.c

    #include <func.h>
    
    int main(int argc, char* argv[])
    {
    	ARGS_CHECK(argc, 3);
    	int fdw = open(argv[1], O_WRONLY);
    	ERROR_CHECK(fdw, -1, "open");
    	int fdr = open(argv[2], O_RDONLY);
    	ERROR_CHECK(fdr, -1, "open");
    	printf("chat2 fdr = %d, fdw = %d
    ", fdr, fdw);
    	char buf[128] = {0};
    	write(fdw, "I am chat2 ",10);
    	read(fdr, buf, sizeof(buf));
    	printf("buf = %s
    ", buf);
    	return 0;
    }
    

    若写端顺序和读端顺序一样会造成死锁,写端必须先写再读,读端先读再写。

    • 同步聊天模型

    chat1.c

    #include <func.h>
    
    int main(int argc, char* argv[])
    {
    	ARGS_CHECK(argc, 3);
    	int fdr = open(argv[1], O_RDONLY);
    	ERROR_CHECK(fdr, -1, "open");
    	int fdw = open(argv[2], O_WRONLY);
    	ERROR_CHECK(fdw, -1, "open");
    	printf("chat1 fdr = %d, fdw = %d
    ", fdr, fdw);
    	char buf[128] = {0};
    	while(1)
    	{
    		memset(buf, 0, sizeof(buf));
    		read(fdr, buf, sizeof(buf));
    		printf("%s
    ", buf);
    		memset(buf, 0, sizeof(buf));
    		read(0, buf, sizeof(buf)); 
    		write(fdw, buf, strlen(buf)-1);
    	}
    	return 0;
    }
    

    chat2.c

    #include <func.h>
    
    int main(int argc, char* argv[])
    {
    	ARGS_CHECK(argc, 3);
    	int fdw = open(argv[1], O_WRONLY);
    	ERROR_CHECK(fdw, -1, "open");
    	int fdr = open(argv[2], O_RDONLY);
    	ERROR_CHECK(fdr, -1, "open");
    	printf("chat2 fdr = %d, fdw = %d
    ", fdr, fdw);
    	char buf[128] = {0};
    	while(1)
    	{
    		memset(buf, 0, sizeof(buf));
    		read(0, buf, sizeof(buf));
    		write(fdw, buf, strlen(buf)-1);
    		memset(buf, 0, sizeof(buf));
    		read(fdr, buf, sizeof(buf));
    		printf("%s
    ", buf);
    	}
    	return 0;
    }
    

    这个模型还有个问题,必须一人说一句,但在实际聊天过程中肯定不是这样的,继续改进。

    • 异步聊天模型

    #include <sys/select.h>

    int select( int nfds, fd_set FAR* readfds, fd_set * writefds, fd_set * exceptfds, const struct timeval * timeout);

    nfds:是一个整数值,是指集合中所有文件描述符的范围,即所有文件描述符的最大值加1,不能错!在Windows中这个参数的值无所谓,可以设置不正确。

    readfds:(可选)指针,指向一组等待可读性检查的套接口。

    writefds:(可选)指针,指向一组等待可写性检查的套接口。

    exceptfds:(可选)指针,指向一组等待错误检查的套接口。

    timeout:select()最多等待时间,对阻塞操作则为NULL。

    chat1.c

    #include <func.h>
    
    int main(int argc, char* argv[])
    {
    	ARGS_CHECK(argc, 3);
    	int fdr = open(argv[1], O_RDONLY);
    	ERROR_CHECK(fdr, -1, "open");
    	int fdw = open(argv[2], O_WRONLY);
    	ERROR_CHECK(fdw, -1, "open");
    	printf("chat1 fdr = %d, fdw = %d
    ", fdr, fdw);
    	char buf[128] = {0};
    	fd_set rdset;
    	int ret;
    	while(1)
    	{
    		FD_ZERO(&rdset);
    		FD_SET(STDIN_FILENO, &rdset);
    		FD_SET(fdr, &rdset);
    		ret = select(fdr + 1, &rdset, NULL, NULL, NULL);
    		if(ret > 0)
    		{
    			if(FD_ISSET(fdr, &rdset))
    			{
    				memset(buf, 0, sizeof(buf));
    				ret = read(fdr, buf, sizeof(buf));
    				if(ret == 0) 
    				{
    					printf("byebye!
    ");
    					break;
    				}
    				printf("%s
    ", buf);
    			}
    			if(FD_ISSET(0, &rdset))
    			{
    				memset(buf, 0, sizeof(buf));
    				ret = read(0, buf, sizeof(buf)); 
    				if(ret == 0) 
    				{
    					printf("byebye!
    ");
    					break;
    				}
    				write(fdw, buf, strlen(buf)-1);
    			}	
    		}
    	}
    	return 0;
    }
    

    chat2.c

    #include <func.h>
    
    int main(int argc, char* argv[])
    {
    	ARGS_CHECK(argc, 3);
    	int fdw = open(argv[1], O_WRONLY);
    	ERROR_CHECK(fdw, -1, "open");
    	int fdr = open(argv[2], O_RDONLY);
    	ERROR_CHECK(fdr, -1, "open");
    	printf("chat2 fdr = %d, fdw = %d
    ", fdr, fdw);
    	char buf[128] = {0};
    	int ret;
    	fd_set rdset;
    	while(1)
    	{
    		FD_ZERO(&rdset);
    		FD_SET(STDIN_FILENO, &rdset);
    		FD_SET(fdr, &rdset);
    		ret = select(fdr + 1, &rdset, NULL, NULL, NULL);
    		if(ret > 0)
    		{
    			if(FD_ISSET(fdr, &rdset))
    			{
    				memset(buf, 0,sizeof(buf));
    				ret = read(fdr, buf, sizeof(buf));
    				if(ret == 0)
    				{
    					printf("byebye!
    ");
    					break;
    				}
    				printf("%s
    ", buf);
    			}
    			if(FD_ISSET(0, &rdset))
    			{
    				memset(buf, 0, sizeof(buf));
    				ret = read(0, buf, sizeof(buf));
    				if(ret == 0)
    				{
    					printf("byebye!
    ");
    					break;
    				}
    				write(fdw, buf, strlen(buf) - 1);
    			}
    		}
    	}
    	return 0;
    }
    

    效果图:

  • 相关阅读:
    [GDKOI2010] 圈地计划(网络流)
    jzoj3454 表白(love)解题报告(01分数规划+DP)
    数论之卢卡斯定理
    POJ1180 Batch Scheduling 解题报告(斜率优化)
    BZOJ 球形空间产生器 解题报告(高斯消元)
    你是怎么封装一个view的
    沙盒目录结构是怎样的?各自用于那些场景?
    这个写法会出什么问题: @property (copy) NSMutableArray *array;
    怎么用 copy 关键字?
    @property后面可以有哪些修饰符?
  • 原文地址:https://www.cnblogs.com/Mered1th/p/10703634.html
Copyright © 2011-2022 走看看