c 的I/O 复用:select()

利用select()监控键盘的输入:如有输入,显示输入字符,如5秒内没有输入,则打印time-out.后,再循环

#include 
#include 
#include 
#include 
#include 
#include 
#include 
#include 
#include 
#include 
#include 
#define  BUF_SIZE 30

int main(void){
    fd_set  reads,temps;   //被监控文件描述符的集合
	int result,str_len;
	char buf[BUF_SIZE];
	struct timeval timeout;
	while(1){
	
	    FD_ZERO(&reads);      //集合个位清0
    	FD_SET(0,&reads);     //0 表示键盘输入,置键盘的文件号0到select的监控集合reads中
	
	                          //特别注意,select经过一个循环后,必须重新清0,置监控位
		temps=reads;       
		timeout.tv_sec=5;    
		timeout.tv_usec=0;
		
		result=select(1,&reads,0,0,&timeout);
		if(result==-1){
			puts("select error");
			break;
		}
		else if(result==0){
			puts("time-out");
		}
		else{
			if(FD_ISSET(0,&temps)){      //0表示键盘输入,如键盘有输入发生,则,temp中就有键盘0文件号
				str_len=read(0,buf,BUF_SIZE);
				buf[str_len]=0;
				printf("message from console:%s\n",buf);
			
			}
		}
	}
	return 0;
}

执行select( )后,reads如是没有读,写,异常的情况发生,全部位清0,所以要循环,必须重新置位。

2. select() 控制键盘读,屏幕的显示

对于select() 对write的监控来说,因为write不像read会阻塞,可以把select()的write理解为是一个开关,如果FD_SET 置位,代表write开关打开,可以对监控文件write,如FD_CLS,清位,表示监控文件不能写。

读可以理解为数据已经存于本机缓冲区后,(缓冲区怎样得到数据这个工作是操作系统完成的),系统再利用select 的读监控通知去缓冲区取数据。

比如键盘输入,我们手工输入字符,操作系统把字符存入电脑缓冲区后,再通知程序利于secect扫描,得知健盘缓冲区有数据后,程序再去取数据,对于程序来讲,取数据的整个过程是没有阻塞的,而是不停地循环,查询各个有变化的文件号。对有变化的文件进行操作。所以省去了大量的取数据的阻塞时间。从这个方面讲,监控集的每个文件的操作时间不应太长,如过久会影响循环查询的效率,进而影响多用户的等待时间。比如例2的显示OK操作过程如是一个无限循环过程,则就永远跳不到下一个键盘输入的操作中。

还有一个编程问题,那就是可以先往select函数导入监控的空集合,再在监控扫描过程中再填加读,写的文件对象,再让新填的文件号在下一个查询循环中起作用,当然也可以随时取消集合中的某个文件号。

 

#include 
#include 
#include 
#include 
#include 
#include 
#include 
#include 
#include 
#include 
#include 
#define  BUF_SIZE 30

int main(void){


    fd_set  reads,temps;   //被监控文件描述符的集合
    fd_set  writes;
	
		int result;
		int str_len;
	char buf[BUF_SIZE];
	struct timeval timeout;

	

	    FD_ZERO(&reads);
    	FD_SET(0,&reads);
		
	    FD_ZERO(&writes);      //写集合
	
	while(1){
		temps=reads;
	
		timeout.tv_sec=50;
		timeout.tv_usec=0;
		
		
		result=select(2,&temps,&writes,0,&timeout); //监控读,写,但写的集合为空
	
	
		if(result==-1){
			puts("select error");
			break;
		}
		
		else if(result==0){
			puts("time-out");
		}
		
       else if(FD_ISSET(1,&writes)){
	     	puts("ok");
	    	sleep(2);
		    FD_CLR(1,&writes);      //清显示,不能显示,此句作用的行也是51句,起作用是下一个select()循环。
    	}
	   
		else if(FD_ISSET(0,&temps)){      
				str_len=read(0,buf,BUF_SIZE); 
				buf[str_len]=0;
				printf("message from console:%s\n",buf);
				
		    	FD_SET(1,&writes);	   //置显示,可以显示,此句作用的行为51句。
			}	
	}
	    
	return 0;
}

 

 

 

 

 

 

 

你可能感兴趣的:(c语言,开发语言)