zoukankan      html  css  js  c++  java
  • UNP学习第六章select

    一、I/O复用典型的网络应用场合

    • 当客户处理多个描述字时,必须使用I/O复用,这在前一段中已做了描述。
    • 一个客户同时处理多个套接口时可能的,但很少出现。
    • 如果一个TCP服务器既要处理监听套接口,又要处理已连接套接口,一般也要用到I/O复用。
    • 如果一个服务器即要处理TCP,又要处理UDP。
    • 如果一个服务器要处理多个服务或者多个协议。

    二、I/O模型

    一个输入操作一般有两个不同的阶段:

    1.等待数据准备好

    2.从内核到进程拷贝数据

    五个I/O模型基本区别:

    • 阻塞I/O

     

    此系统调用直到数据报到达切拷贝到应用缓冲区或是出错才返回。

    • 非阻塞I/O模型

     

    前三次调用recvfrom任无数据返回,因此内核立即返回一个EWOULDBLOCK错误。

    第四次调用recvfrom时,数据已准备好,被拷贝到应用缓冲区,recvfrom返回成功指示。

    一直调用recvfrom称之为轮询,这会对CPU时间极大浪费。

    • I/O复用模型

    调用select或poll,在这两个系统调用中的某一个上阻塞,而不是阻塞于真正的I/O系统调用。

    我们阻塞select调用,等待数据报套接口可读。当select返回套接口可读条件时,我们调用recvfrom将数据报拷贝到应用缓冲区中。

    这一种和第一种比较没有什么优越性,而且调用了两次系统调用。但是select可以等待多个描述字。

    • 信号驱动I/O模型

     我们也可以用信号,让内核描述字准备好时用信号SIGIO通知我们。

    先要允许套接口进行信号驱动I/O,并通过系统调用sigaction安装一个信号处理程序。

    此系统调用立即返回,进程继续工作,它是非阻塞的。数据准备好被读时,就为该进程生成一个SIGIO信号。

    我们可以在信号处理程序中调用recvfrom来读取数据报,并通知主循环来处理。(也可以通知主循环读取)

    信号的好处是,不阻塞,主循环可以继续执行。

    • 异步I/O模型

     

    和上一个信号驱动I/O由内核通知我们何时可以启动一个I/O操作,异步I/O是由内核通知我们I/O操作何时完成。

    三、select函数

    #include <sys/select.h>
    #include <sys/time.h>
    
    int select(int maxfdp1, fd_set *readset, fd_set *writeset, fd_set *exceptset
        const struct timeval *timeout);
    返回:准备好描述字的正数目0超时,-1出错
    maxfdp1:整数值,集合中所有文件描述符范围,所有文件描述符中的最大值+1
    readset:指向一组等待可读性检查的套接口
    writeset:指向一组等待可写性检查的套接口
    exceptset:指向一组等待错误检查的套接口
    timeout:select()最多等待时间,对阻塞操作则为NULL

    timeout有三种可能:

    1.永远等待下去:仅在有一个描述字准备好I/O时才返回,为此,我们将参数timeout设置为空指针

    2.等待固定时间:再有一个描述字准备好I/O后返回,但不超过timeout

    3.根本不等待:检查描述字后立即返回,这称为轮询。timeout指向0

     对于上面的fd_set数据类型,唯一可以进行处理的是:分配一个这种类型的变量,将这种类型的一个变量赋值给同类的另一个变量,或使用下面函数。

    #include <sys/select.h>
    
    int FD_ISSET(int fd, fd_set *fdset);  /*在调用select()函数后,用FD_ISSET来检测fd是否在set集合中,当检测到fd在set中则返回真,否则,返回假(0)*/
    返回:若fd在描述符集中,返回非0值,否则返回0
    void FD_CLR(int fd, fd_set *fdset);  /*将fd从set集合中清除*/
    void FD_SET(int fd, fd_set *fdset);  /*将fd加入set集合*/
    void FD_ZERO(fd_set *fdset);  /*将set清零使集合中不含任何fd*/

     相关的还有fd_set

    typedef struct
    {
    /*XPG4.2requires this member name.Otherwise avoid the name
    from the global name space.*/
    #ifdef__USE_XOPEN
    __fd_maskfds_bits[__FD_SETSIZE/__NFDBITS];
    #define__FDS_BITS(set)((set)->fds_bits)
    #else
    __fd_mask__fds_bits[__FD_SETSIZE/__NFDBITS];
    #define__FDS_BITS(set)((set)->__fds_bits)
    #endif
    }fd_set;
    无欲速,无见小利。欲速,则不达;见小利,则大事不成。
  • 相关阅读:
    第一个Django demo
    内建函数
    Git积累
    区间dp
    【Spring】Spring AOP详解(转载)
    【git】git 常用命令(含删除文件)
    【idea】idea如何在maven工程中引入jar包
    【Java】Scanner类nextInt后使用nextLine无法读取输入
    【Java_Eclipse】Eclipse插件如何卸载?
    【MySQL】MySQL5.7等以上版本在Windows上的配置
  • 原文地址:https://www.cnblogs.com/ch122633/p/8445114.html
Copyright © 2011-2022 走看看