IO模型(阻塞IO,非阻塞IO,IO多路复用)

1、阻塞IO

读阻塞:当对文件描述符进行读操作时,如果没有资源分配则进入阻塞状态。read、recv…

​ 写阻塞:当对文件描述符进行写操作时,如果没有足够空间,则进入阻塞状态。 write、send…

​ 特殊:accept、connect

​ 缺点:当用户使用阻塞IO进行IO操作时,有可能会阻碍其他程序的正常运行

2、非阻塞IO

​ 特点:当使用非阻塞IO,没有资源(输入或者输出)时,IO函数不会阻塞,而是会立即返回

​ 缺点:因为非阻塞IO函数在频繁调用时会消耗大量系统资源

将阻塞IO设置为非阻塞IO的方法:fcntl

   #include <unistd.h>
   #include <fcntl.h>

   int fcntl(int fd, int cmd, ... /* arg */ );
  		参数:
  			fd:文件描述符
  			cmd:命令
            	F_GETFL -- 获取文件描述符属性状态的值
            	F_SETFL -- 设置文件描述符属性状态的值
            	
  				文件描述符的状态标志,用于表示非阻塞特性 -- O_NONBLOCK		
  				
   		返回值:
   			根据cmd的不同,会有不同的返回值

   		例:
   			1、获取文件描述符对应的属性状态标志
   				int flags = fcntl(0, F_GETFL, 0);
   			2、添加非阻塞属性
   				flags = flags | O_NONBLOCK;
   			3、设置非阻塞
   				fcntl(0, F_SETFL, flags);
3、IO多路复用

​ IO多路可以对用户指定的文件描述符做统一的监测

(1)select机制

监测表为位图表

   #include <sys/select.h>
   #include <sys/time.h>
   #include <sys/types.h>
   #include <unistd.h>

   int select(int nfds, fd_set *readfds, fd_set *writefds,
              fd_set *exceptfds, struct timeval *timeout);
   参数:
   	nfds:三张监测表中最大的文件描述符的值+1
   	readfds:读监测表的首地址,如果不进行读监测,可以填NULL
   	writefds:写监测表的首地址,如果不进行写监测,可以填NULL
   	exceptfds:异常监测表的首地址,如果不进行异常监测,可以填NULL
   	timeout:设置的超时时间的首地址,如果不设置超时时间,可以填NULL
   
   返回值:
   	成功返回三个文件描述符监测表中的监测文件个数,失败返回-1,如果返回0表示超时
   	
   	   //删除文件描述符
       void FD_CLR(int fd, fd_set *set);
       //判断文件描述符是否有响应
       int  FD_ISSET(int fd, fd_set *set);
       //添加文件描述符
       void FD_SET(int fd, fd_set *set);
       //清空监测表
       void FD_ZERO(fd_set *set);	

    	超时时间类型的结构体   
   		struct timeval {
               long    tv_sec;         /* seconds */   秒
               long    tv_usec;        /* microseconds */  微秒
        };
        例:
        	struct timeval mytime;
        	mytime.tv_sec = 5;
        	mytime.tv_usec = 0;

      	select监测流程:
      		int sockfd =scoket();
      	1、创建监测表,初始化监测表(清0)
      		fd_set rfds;
      		FD_ZERO(&rfds);	
      	2、向监测表中添加文件描述符
      		FD_SET(sockfd, &rfds);
      	3、循环监测表 -- select
      		int max_fd = fd+1;
      		while(1)
      		{
      			ret = select(max_fd, &rfds, NULL, NULL, &mytime);
      			if(ret < 0)
      			{
      				perror("select");
      				exit(-1);
      			}
      			for(int i = 0; i < max_fd; i++)
      			{
      				if(FD_ISSET(i, &rfds))
      				{
      					if(i == sockfd)
      					{
      						connfd = accept();
      						FD_SET(connfd, &rfds);
      					}
      					else
      					{
      						ret = read();
                            if(ret == 0)
                            {
                            	FD_CLR(i, &rfds)
                            	close(i);
                            }
      					}
      				}
      			}      			
      		}
    
    	注意:每一次监测之前需要还原初始表,因为在监测成功之后,初始表会发生变化

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值