zoukankan      html  css  js  c++  java
  • 认识epoll

    linux下的epoll(7)函数,其有着良好的就绪事件通知机制。Epoll 是被linux2.6开始引进的,但是不被其他的类UNIX系统支持,它提供了一种类似select或poll函数的机制:
    a. Select(2)只能够同时管理FD_SETSIZE(默认为1024)数目的文件描述符,并且必须遍历所有的描述符来检查就绪的描述符。
    b. poll(2)没有固定的描述符上限这一限制,但是每次必须遍历所有的描述符来检查就绪的描述符,这个过程的时间复杂度为O(n)。
    epoll没有select这样对文件描述符上限的限制,也不会像select/poll那样进行线性的遍历。因此epoll处理大并发连接有着更高的性能。

    我们从select那里仅仅知道了,有I/O事件发生了,但却并不知道是那几个流(可能有一个,多个,甚至全部),我们只能无差别轮询所有流,找出能读出数据,或者写入数据的流,对他们进行操作。
    但是使用select,我们有O(n)的无差别轮询复杂度,同时处理的流越多,每一次无差别轮询时间就越长。
    epoll可以理解为event poll,不同于忙轮询和无差别轮询,epoll只会把哪个流发生了怎样的I/O事件通知我们(时间复杂度降低到了O(1))。此时我们对这些流的操作都是有意义的。


    Epoll相关操作函数介绍:
    1. epoll_create(2) or epoll_create1(2)(有着不同的参数值)用来创建epoll实例。
    /usr/include/sys/epoll.h
    extern int epoll_create (int __size) ;
    RETURN:>0, 成功;-1, 出错
    函数描述:
    (1) epoll_create返回的是一个文件描述符,也就是说epoll是以特殊文件的方式体现给用户
    (2) __size提示操作系统,用户可能要使用多少个文件描述符,该参数已经废弃,填写一个大于0的正整数

    2. epoll_ctl(2)用来增加或移除被epoll所监听的文件描述符。

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

    RETURN:0,成功;-1,出错

    函数描述:
    (1) epfd为epoll_create创建的epoll描述符
    (2) epoll_ctl函数对epoll进行op类型的操作,op选项为
    EPOLL_CTL_ADD,对fd描述符注册event事件
    EPOLL_CTL_MOD,对fd描述符的event事件进行修改
    EPOLL_CTL_DEL,删除已注册的event事件

    3. epoll_wait(2)用来等待发生在监听描述符上的事件。它会一直阻塞直到事件发生。
    #include

    int epoll_wait(int epfd, struct epoll_event *events,
    int maxevents, int timeout);

    RETURN:>0,发生事件个数;=0,时间到;-1,出错

    函数描述:
    epoll_wait与select函数类似,同步地等待事件发生
    (1) epfd,标识epoll的文件描述符
    (2) events,指向传入操作系统的一个epoll_event数组
    (3) maxevents,表示传入数组的大小,必须大于0
    当有事件发生,Linux会填写events结构,返回给应用程序。由于epoll_wait同步等待,有可能被信号中断,返回EINTR错误.
    这里有一个比较重要的问题:从epoll_wait返回的events中,该如何知道是哪个描述符上的事件:在注册epoll事件的时候,一定要填写epoll_data,否则我们将分不清触发的是哪个描述符上的事件。
    Epoll的两种模式:
    1. 水平触发(LT):使用此种模式,当数据可读的时候,epoll_wait()将会一直返回就绪事件。如果你没有处理完全部数据,并且再次在该 epoll实例上调用epoll_wait()才监听描述符的时候,它将会再次返回就绪事件,因为有数据可读。LT(level triggered)是缺省的工作方式,并且同时支持block和no-block socket.。
    2. 边缘触发(ET):使用此种模式,只能获取一次就绪通知,如果没有处理完全部数据,并且再次调用epoll_wait()的时候,它将会阻塞,因为就绪事件已经释放出来了。ET只支持非阻塞socket。
    ET的效能更高,但是对程序员的要求也更高。在ET模式下,我们必须一次干净而彻底地处理完所有事件。
    传递给epoll_ctl(2)的Epoll事件结构体如下所示:

    typedef union epoll_data
    {
    void*ptr;
    intfd;
    __uint32_t u32;
    __uint64_t u64;
    }epoll_data_t;
    
    struct epoll_event
    {
    __uint32_t events;/* Epoll events */
    epoll_data_t data;/* User data variable */
    };

    对于每一个监听的描述符,能够关联一个整形数据或指向用户数据的指针。

    epoll的事件类型:
    – EPOLLIN,读事件
    – EPOLLOUT,写事件
    – EPOLLPRI,带外数据,与select的异常事件集合对应
    – EPOLLRDHUP,2.6.17 版本内核中增加了 EPOLLRDHUP 事件,代表对端断开连接(参见EPOLL事件之EPOLLRDHUP)
    – EPOLLERR,错误事件
    – EPOLLET,设置事件为边沿触发
    – EPOLLONESHOT,只触发一次,事件自动被删除
    一个文件描述符在一个epoll实例上只能注册一次,一个描述符在同一个epoll实例上注册多次,会产生EEXIST的错误。
    同样,删除epoll的事件,只需描述符就够了
    epoll_ctl(epfd, EPOLL_CTL_DEL, fd, NULL);

    引用:

    epoll实例

    epoll 或者 kqueue 的原理是什么?

  • 相关阅读:
    Running ASP.NET Applications in Debian and Ubuntu using XSP and Mono
    .net extjs 封装
    ext direct spring
    install ubuntu tweak on ubuntu lts 10.04,this software is created by zhouding
    redis cookbook
    aptana eclipse plugin install on sts
    ubuntu open folderpath on terminal
    ubuntu install pae for the 32bit system 4g limited issue
    EXT Designer 正式版延长使用脚本
    用 Vagrant 快速建立開發環境
  • 原文地址:https://www.cnblogs.com/lijingcheng/p/4454894.html
Copyright © 2011-2022 走看看