zoukankan      html  css  js  c++  java
  • IO复用函数select poll epoll

    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

    1. 第一个参数maxfdp1指定待测试的描述字个数,它的值是待测试的最大描述字加1.
    2. 中间的三个参数readset、writeset和exceptset指定我们要让内核测试读、写和异常条件的描述字。如果对某一个的条件不感兴趣,就可以把它设为空指针。struct fd_set可以理解为一个集合,这个集合中存放的是文件描述符,可通过以下四个宏进行设置:
    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);   // 检查集合中指定的文件描述符是否可以读写 
    1. timeout告知内核等待所指定描述字中的任何一个就绪可花多少时间。其timeval结构用于指定这段时间的秒数和微秒数。
    struct timeval{
        long tv_sec;   //seconds
        long tv_usec;  //microseconds
    };

    poll

    #include <poll.h>
    int poll ( struct pollfd * fds, unsigned int nfds, int timeout);

    pollfd结构体定义如下:

    struct pollfd {
        int fd;         /* 文件描述符 */
        short events;         /* 等待的事件 */
        short revents;       /* 实际发生了的事件 */
    } ; 

    fd成员指定文件描述符,events成员告诉poll监听fd上的哪些事件,它是一系列事件的按位或;revents成员则有内核修改,以通知应用程序fd上实际发生了哪些事件.

    poll事件类型:

    事件 描述
    POLLIN 有数据可读
    POLLRDNORM 有普通数据可读。
    POLLRDBAND 有优先数据可读。
    POLLPRI 有紧迫数据可读。
    POLLOUT 写数据不会导致阻塞。
    POLLWRNORM 写普通数据不会导致阻塞。
    POLLWRBAND 写优先数据不会导致阻塞。
    POLLMSGSIGPOLL 消息可用。

    此外,revents域中还可能返回下列事件:

    事件 描述
    POLLER 指定的文件描述符发生错误。
    POLLHUP 指定的文件描述符挂起事件。
    POLLNVAL 指定的文件描述符非法。

    epoll

    #include <sys/epoll.h>
    int epoll_create(int size);
    int epoll_ctl(int epfd, int op, int fd, struct epoll_event *event);
    int epoll_wait(int epfd, struct epoll_event * events, int maxevents, int timeout);
    int epoll_create(int size);

    创建一个epoll的句柄,size用来告诉内核这个监听的数目一共有多大,这个参数不同于select()中的第一个参数,给出最大监听的fd+1的值,参数size并不是限制了epoll所能监听的描述符最大个数,只是对内核初始分配内部数据结构的一个建议
    当创建好epoll句柄后,它就会占用一个fd值,在linux下如果查看/proc/进程id/fd/,是能够看到这个fd的,所以在使用完epoll后,必须调用close()关闭,否则可能导致fd被耗尽。

    int epoll_ctl(int epfd, int op, int fd, struct epoll_event *event);

    函数是对指定描述符fd执行op操作。
    - epfd:是epoll_create()的返回值。
    - op:表示op操作,用三个宏来表示:添加EPOLL_CTL_ADD,删除EPOLL_CTL_DEL,修改EPOLL_CTL_MOD。分别添加、删除和修改对fd的监听事件。
    - fd:是需要监听的fd(文件描述符)
    - epoll_event:是告诉内核需要监听什么事,struct epoll_event结构如下:

    struct epoll_event {
      __uint32_t events;  /* Epoll events */
      epoll_data_t data;  /* User data variable */
    };
    
    //events可以是以下几个宏的集合:
    EPOLLIN :表示对应的文件描述符可以读(包括对端SOCKET正常关闭);
    EPOLLOUT:表示对应的文件描述符可以写;
    EPOLLPRI:表示对应的文件描述符有紧急的数据可读(这里应该表示有带外数据到来);
    EPOLLERR:表示对应的文件描述符发生错误;
    EPOLLHUP:表示对应的文件描述符被挂断;
    EPOLLET: 将EPOLL设为边缘触发(Edge Triggered)模式,这是相对于水平触发(Level Triggered)来说的。
    EPOLLONESHOT:只监听一次事件,当监听完这次事件之后,如果还需要继续监听这个socket的话,需要再次把这个socket加入到EPOLL队列里
    int epoll_wait(int epfd, struct epoll_event * events, int maxevents, int timeout);

    等待epfd上的io事件,最多返回maxevents个事件。
    参数events用来从内核得到事件的集合,maxevents告之内核这个events有多大,这个maxevents的值不能大于创建epoll_create()时的size,参数timeout是超时时间(毫秒,0会立即返回,-1将不确定,也有说法说是永久阻塞)。该函数返回需要处理的事件数目,如返回0表示已超时。

    工作模式

    epoll对文件描述符的操作有两种模式:LT(level trigger)和ET(edge trigger)。LT模式是默认模式,LT模式与ET模式的区别如下:
      LT模式:当epoll_wait检测到描述符事件发生并将此事件通知应用程序,应用程序可以不立即处理该事件。下次调用epoll_wait时,会再次响应应用程序并通知此事件。
      ET模式:当epoll_wait检测到描述符事件发生并将此事件通知应用程序,应用程序必须立即处理该事件。如果不处理,下次调用epoll_wait时,不会再次响应应用程序并通知此事件。

  • 相关阅读:
    [ Algorithm ] N次方算法 N Square 动态规划解决
    [ Algorithm ] LCS 算法 动态规划解决
    sql server全文索引使用中的小坑
    关于join时显示no join predicate的那点事
    使用scvmm 2012的动态优化管理群集资源
    附加数据库后无法创建发布,error 2812 解决
    浅谈Virtual Machine Manager(SCVMM 2012) cluster 过载状态检测算法
    windows 2012 r2下安装sharepoint 2013错误解决
    sql server 2012 数据引擎任务调度算法解析(下)
    sql server 2012 数据引擎任务调度算法解析(上)
  • 原文地址:https://www.cnblogs.com/nickqiao/p/7583331.html
Copyright © 2011-2022 走看看