zoukankan      html  css  js  c++  java
  • I/O复用

    一、I/O复用概述

    I/O复用概念:

    解决进程或线程阻塞到某个 I/O 系统调用而出现的技术,使进程不阻塞于某个特定的 I/O 系统调

    I/O复用使用的场合:

    1.当客户处理多个描述符(通常是交互式输入、网络套接字)时,必须使用I/O复用。

    2.tcp服务器既要处理监听套接字,又要处理已连接套接字,一般要使用I/O复用。

    3.如果一个服务器既要处理tcp又要处理udp,一般要使用I/O复用。

    4.如果一个服务器要处理多个服务或多个服务时,一般要使用I/O复用。

    I/O复用常用函数:

    select、poll

    二、select()函数

    select函数介绍:

    int select(int maxfd, fd_set *readset, fd_set *writeset, fd_set *exceptset, const struct timeval *timeout);
    功能:轮询扫描多个描述符中的任一描述符是否发生响应,或经过一段时间后唤醒
    参数:
    参数 名称 说明
    maxfd 指定要检测的描述符的范围 所检测描述符最大值+1
    readset 可读描述符集 监测该集合中的任意描述符是否有数据可读
    writeset 可写描述符集 监测该集合中的任意描述符是否有数据可写
    exceptset 异常描述符集 监测该集合中的任意描述符是否发生异常
    timeout 超时时间 超过规定时间后唤醒

    返回值:

    0:超时

    -1:出错

    >0:准备好的文件描述符数量

    头文件:

    [csharp] view plain copy
     
    print?
    1. #include <sys/select.h>  
    2. #include <sys/time.h>  
    #include <sys/select.h>
    #include <sys/time.h>

    超时时间

    [csharp] view plain copy
     
    print?
    1. //该结构体表示等待超时的时间  
    2. struct timeval{  
    3.     long tv_sec;//秒  
    4.     long tv_usec;//微秒  
    5. };  
    6.   
    7. //比如等待10.2秒  
    8. struct timeval timeout;  
    9. timeoout.tv_sec = 10;  
    10. timeoout.tv_usec = 200000;  
    11.   
    12. //将select函数的timeout参数设置为NULL则永远等待  
    //该结构体表示等待超时的时间
    struct timeval{
    	long tv_sec;//秒
    	long tv_usec;//微秒
    };
    
    //比如等待10.2秒
    struct timeval timeout;
    timeoout.tv_sec = 10;
    timeoout.tv_usec = 200000;
    
    //将select函数的timeout参数设置为NULL则永远等待

    描述符集合的操作:

    select()函数能对多个文件描述符进行监测,如果一个参数对应一个描述符,那么select函数的4个参数最多能监测4个文件描述,那他如何实现对多个文件描述符的监测的呢?

    大家想一想文件描述符基本具有3种特性(读、写、异常),如果我们统一将监测可读的描述符放入可读集合(readset),监测可写的描述符放入可写集合(writeset),监测异常的描述符放入异常集合(exceptset)。然后将这3个集合传给select函数,是不是就可监测多个描述符呢.

    如何将某个描述符加入到特定的集合中呢?这时就需要了解下面的集合操作函数

    [csharp] view plain copy
     
    print?
    1. /初始化描述符集  
    2. void FD_ZERO(fd_set *fdset);  
    3.   
    4. //将一个描述符添加到描述符集  
    5. void FD_SET(int fd, fd_set *fdset);  
    6.   
    7. //将一个描述符从描述符集中删除  
    8. void FD_CLR(int fd, fd_set *fdset);  
    9.   
    10. //检测指定的描述符是否有事件发生  
    11. int FD_ISSET(int fd, fd_set *fdset);  
    /初始化描述符集
    void FD_ZERO(fd_set *fdset);
    
    //将一个描述符添加到描述符集
    void FD_SET(int fd, fd_set *fdset);
    
    //将一个描述符从描述符集中删除
    void FD_CLR(int fd, fd_set *fdset);
    
    //检测指定的描述符是否有事件发生
    int FD_ISSET(int fd, fd_set *fdset);
    

    select()函数整体使用框架:

    例子:检测 0、4、5 描述符是否准备好

    [csharp] view plain copy
     
    print?
    1. while(1)  
    2. {  
    3.     fd_set rset;//创建一个描述符集rset  
    4.     FD_ZERO(&rset);//对描述符集rset清零  
    5.     FD_SET(0, &rset);//将描述符0加入到描述符集rset中  
    6.     FD_SET(4, &rset);//将描述符4加入到描述符集rset中  
    7.     FD_SET(5, &rset);//将描述符5加入到描述符集rset中  
    8.       
    9.     if(select(5+1, &rset, NULL, NULL, NULL) > 0)  
    10.     {  
    11.         if(FD_ISSET(0, &rset))  
    12.         {  
    13.             //描述符0可读及相应的处理代码  
    14.         }  
    15.           
    16.         if(FD_ISSET(4, &rset))  
    17.         {  
    18.             //描述符4可读及相应的处理代码  
    19.         }  
    20.         if(FD_ISSET(5, &rset))  
    21.         {  
    22.             //描述符5可读及相应的处理代码  
    23.         }  
    24.     }  
    25. }  
    while(1)
    {
    	fd_set rset;//创建一个描述符集rset
    	FD_ZERO(&rset);//对描述符集rset清零
    	FD_SET(0, &rset);//将描述符0加入到描述符集rset中
    	FD_SET(4, &rset);//将描述符4加入到描述符集rset中
    	FD_SET(5, &rset);//将描述符5加入到描述符集rset中
    	
    	if(select(5+1, &rset, NULL, NULL, NULL) > 0)
    	{
    		if(FD_ISSET(0, &rset))
    		{
    			//描述符0可读及相应的处理代码
    		}
    		
    		if(FD_ISSET(4, &rset))
    		{
    			//描述符4可读及相应的处理代码
    		}
    		if(FD_ISSET(5, &rset))
    		{
    			//描述符5可读及相应的处理代码
    		}
    	}
    }
  • 相关阅读:
    C6678图像处理板卡学习资料第426篇:基于XC7Z100+TMS320C6678的图像处理板卡
    无线通信板卡学习资料第427篇:基于3U VPX XC7Z035+AD9361的无线通信板卡
    硬件加速卡学习资料第1篇:基于Xilinx XCKU115的半高PCIe x8 硬件加速卡 FPGA硬件加速
    硬件加速卡学习资料第1篇:基于Xilinx XCKU115的半高PCIe x8 硬件加速卡 FPGA硬件加速
    PCIe 加速计算卡学习资料第420篇:基于ZU19EG的4路100G光纤的PCIe 加速计算卡
    GPU计算主板学习资料第735篇:基于3U VPX的AGX Xavier GPU计算主板 信号计算主板 视频处理 相机信号
    [个人翻译]GitHub指导文件(GitHub Guides[Hello World])
    关于“如何只用2GB内存从20亿,40亿,80亿个整数中找到出现次数最多的数?”的一种思路
    [RabbitMQ]Windows环境下rabbitmqclt(Command Line Tools)出现Erlang distribution failed错误的解决方法
    Visual Studio无法推送提交到Github的解决方法
  • 原文地址:https://www.cnblogs.com/tianlangshu/p/6795695.html
Copyright © 2011-2022 走看看