• epoll


    select poll epoll系统调用详细分析

     

    epoll是Linux内核为处理大批量文件描述符而作了改进的poll,是Linux下多路复用IO接口select/poll的增强版本,它能显著提高程序在大量并发连接中只有少量活跃的情况下的系统CPU利用率。另一点原因就是获取事件的时候,它无须遍历整个被侦听的描述符集,只要遍历那些被内核IO事件异步唤醒而加入Ready队列的描述符集合就行了。epoll除了提供select/poll那种IO事件的水平触发(Level Triggered)外,还提供了边缘触发(Edge Triggered),这就使得用户空间程序有可能缓存IO状态,减少epoll_wait/epoll_pwait的调用,提高应用程序效率。

     

    epoll的EPOLLLT模式和EPOLLET模式比较

    http://blog.csdn.net/lcabcdefg/article/details/7243277

    epoll是linux系统最新的处理多连接的高效率模型, 工作在两种方式下, EPOLLLT方式和EPOLLET方式。

    EPOLLLT是系统默认, 工作在这种方式下, 程序员不易出问题, 在接收数据时,只要socket输入缓存有数据,

    都能够获得EPOLLIN的持续通知, 同样在发送数据时, 只要发送缓存够用, 都会有持续不间断的EPOLLOUT

    通知。而对于EPOLLET是另外一种触发方式, 比EPOLLLT要高效很多, 对程序员的要求也多些, 程序员必须

    小心使用,因为工作在此种方式下时, 在接收数据时, 如果有数据只会通知一次, 假如read时未读完数据,

    那么不会再有EPOLLIN的通知了, 直到下次有新的数据到达时为止; 当发送数据时, 如果发送缓存未满也只有

    一次EPOLLOUT的通知, 除非你把发送缓存塞满了, 才会有第二次EPOLLOUT通知的机会, 所以在此方式下

    read和write时都要处理好。 暂时写到这里, 留作备忘。

            附加: 如果将一个socket描述符添加到两个epoll中, 那么即使在EPOLLET模式下, 只要前一个epoll_wait时,未读完, 那么后一个epoll_wait事件时, 也会得到读的通知, 但前一个读完的情况下, 后一个epoll就不会得到读事件的通知了。。。。。

     

    epoll和select区别

    http://blog.csdn.net/ysu108/article/details/7570571

    区别(epoll相对select优点)主要有三:

    1.select的句柄数目受限,在linux/posix_types.h头文件有这样的声明:#define __FD_SETSIZE    1024  表示select最多同时监听1024个fd。而epoll没有,它的限制是最大的打开文件句柄数目。

    2.epoll的最大好处是不会随着FD的数目增长而降低效率,在selec中采用轮询处理,其中的数据结构类似一个数组的数据结构,而epoll 是维护一个队列,直接看队列是不是空就可以了。epoll只会对"活跃"的socket进行操作---这是因为在内核实现中epoll是根据每个fd上面 的callback函数实现的。那么,只有"活跃"的socket才会主动的去调用 callback函数(把这个句柄加入队列),其他idle状态句柄则不会,在这点上,epoll实现了一个"伪"AIO。但是如果绝大部分的I/O都是 “活跃的”,每个I/O端口使用率很高的话,epoll效率不一定比select高(可能是要维护队列复杂)

    3.使用mmap加速内核与用户空间的消息传递。无论是select,poll还是epoll都需要内核把FD消息通知给用户空间,如何避免不必要的内存拷贝就很重要,在这点上,epoll是通过内核于用户空间mmap同一块内存实现的。

    注:第三点貌似有问题. epoll的内核实现中并没有使用到mmap. 示例如下:

    在epoll_ctl中,有:

    1141 /*                                                                                                        
    1142  * The following function implements the controller interface for                                         
    1143  * the eventpoll file that enables the insertion/removal/change of                                        
    1144  * file descriptors inside the interest set.                                                              
    1145  */                                                                                                       
    1146 SYSCALL_DEFINE4(epoll_ctl, int, epfd, int, op, int, fd,                                                   
    1147         struct epoll_event __user *, event)                                                               
    1148 {                                                                                                         
    1149     int error;                                                                                            
    1150     struct file *file, *tfile;                                                                            
    1151     struct eventpoll *ep;                                                                                 
    1152     struct epitem *epi;                                                                                   
    1153     struct epoll_event epds;                                                                              
    1154                                                                                                           
    1155     DNPRINTK(3, (KERN_INFO "[%p] eventpoll: sys_epoll_ctl(%d, %d, %d, %p)
    ",                             
    1156              current, epfd, op, fd, event));                                                              
    1157                                                                                                           
    1158     error = -EFAULT;                                                                                      
    1159     if (ep_op_has_event(op) &&                                                                            
    1160         copy_from_user(&epds, event, sizeof(struct epoll_event)))                                         
    1161         goto error_return;   
    

    在epoll_wait中,最终会调到此函数:

     945         /*
     946          * Is the event mask intersect the caller-requested one,
     947          * deliver the event to userspace. Again, we are holding                                          
     948          * "mtx", so no operations coming from userspace can change                                       
     949          * the item.
     950          */
     951         if (revents) {
     952             if (__put_user(revents,
     953                        &events[eventcnt].events) ||
     954                 __put_user(epi->event.data,
     955                        &events[eventcnt].data))                                                           
     956                 goto errxit;
     957             if (epi->event.events & EPOLLONESHOT)
     958                 epi->event.events &= EP_PRIVATE_BITS;
     959             eventcnt++;
     960         }
    

    其中put_user --  Write a simple value into user space. This function may sleep.

    copy_to_user,copy_from_user,get_user,put_user函数比较

     注:epoll_create中的参数没有什么用

     1133 SYSCALL_DEFINE1(epoll_create, int, size)                                                                  
    1134 {                                                                                                         
    1135     if (size <= 0)                                                                                        
    1136         return -EINVAL;                                                                                   
    1137                                                                                                           
    1138     return sys_epoll_create1(0);                                                                          
    1139 }  
    

     EPOLL的内核实现

     epoll的内核实现

    1. select/poll的缺点

         A. 每次调用时重复的从用户态读入参数

         B. 每次调用时全量的扫描文件描述符

         C. 每次调用开始,将进程加入到每个文件描述符的等待队列,在调用结束后又把进程从等待队列中删除。

         D. 在不修改内核的情况下,select最多支持1024个文件描述符。

    epoll完整实例

    http://www.cppblog.com/API/archive/2013/07/01/201424.html

    求教:epoll的ET模式对EPOLLOUT事件怎么处理的?

    有关epoll的EPOLLOUT

    三种使用场景:

      1: 对客户端socket只使用EPOLLIN(读)监听,不监听EPOLLOUT(写),写操作一般使用socket的send操作

      2:客户端的socket初始化为EPOLLIN(读)监听,有数据需要发送时,对客户端的socket修改为EPOLLOUT(写)操作,这时EPOLL机制会回调发送数据的函数,发送完数据之后,再将客户端的socket修改为EPOLL(读)监听

     3:对客户端socket使用EPOLLIN 和 EPOLLOUT两种操作,这样每一轮epoll_wait循环都会回调读,写函数,这种方式效率不是很好

  • 相关阅读:
    python学习--大数据与科学计算第三方库简介
    养生轴---茶轴
    MobaXterm的安装和使用
    如何解决RIP的问题
    评论博客时注意的地方
    回忆老师教学博客
    助教自我介绍
    《构建之法》读书笔记1
    插入排序
    总结之H3C汇聚层交换机认证在线人数展示系统
  • 原文地址:https://www.cnblogs.com/jingzhishen/p/3429761.html
Copyright © 2020-2023  润新知