poll&&epoll实现分析(二)——epoll实现

Epoll实现分析——作者:lvyilong316

通过上一章分析,poll运行效率的两个瓶颈已经找出,现在的问题是怎么改进。首先,如果要监听1000fd每次poll都要把1000fd 拷入内核,太不科学了,内核干嘛不自己保存已经拷入的fd呢?答对了,epoll就是自己保存拷入的fd,它的API就已经说明了这一点——不是 epoll_wait的时候才传入fd,而是通过epoll_ctl把所有fd传入内核再一起"wait",这就省掉了不必要的重复拷贝。其次,在 epoll_wait时,也不是把current轮流的加入fd对应的设备等待队列,而是在设备等待队列醒来时调用一个回调函数(当然,这就需要唤醒回调机制),把产生事件的fd归入一个链表,然后返回这个链表上的fd

转载请尊重原创、保留相关链接本文来自多宝平台http://www.mbodb.com
    另外,epoll机制实现了自己特有的文件系统eventpoll filesystem

1. 内核数据结构

(1) struct eventpoll {  

    spinlock_t lock;  

      struct mutex mtx;  

      wait_queue_head_t wq;  /* Wait queue used by sys_epoll_wait() ,调用epoll_wait()我们就是""在了这个等待队列上*/

 wait_queue_head_t poll_wait;  /* Wait queue used by file->poll() , 这个用于epollfd本事被poll的时候*/

 struct list_head rdllist; /* List of ready file descriptors, 所有已经readyepitem都在这个链表里面*/ 

 structrb_root rbr; /* RB tree root used to store monitored fd structs, 所有要监听的epitem都在这里*/ 

epitem *ovflist;  /*存放的epitem都是我们在传递数据给用户空间时监听到了事件*/.

 struct user_struct *user; /*这里保存了一些用户变量,比如fd监听数量的最大值等*/  

};  

通过epoll_ctl接口加入该epoll描述符监听的套接字则属于socket filesystem,这点一定要注意。每个添加的待监听(这里监听和listen调用不同)都对应于一个epitem结构体,该结构体已红黑树的结构组织,eventpoll结构中保存了树的根节点(rbr成员)。同时有监听事件到来的套接字的该结构以双向链表组织起来,链表头保存在eventpoll中(rdllist成员)。

/* 

 * Each file descriptor added to the eventpoll interface will  have an entry of this type linked to the "rbr" RB tree. 

 */  

(2) struct epitem {  

    struct rb_node rbn;      /* RB tree node used to link this structure to the eventpoll RB tree */  

struct list_head rdllink;  /* 链表节点所有已经readyepitem都会被链到eventpollrdllist */ 

    struct epitem *next;  

    struct epoll_filefd ffd;    /* The file descriptor information this item refers to */

    int nwait;   /* Number of active wait queue attached to poll operations */

    struct list_head pwqlist;  /* List containing poll wait queues */  

    struct eventpoll *ep;  /* The "container" of this item */ 

    struct list_head fllink; /* List header used to link this item to the "struct file" items list */ 

 struct epoll_event event;   /*当前的epitem关系哪些events, 这个数据是调用epoll_ctl时从用户态传递过来 */ 

};  

(3) struct epoll_filefd {

struct file *file;

int fd;};

(4)  struct eppoll_entry { /* Wait structure used by the poll hooks */

struct list_head llink; /* List header used to link this structure to the "struct epitem" */

struct epitem *base; /* The "base" pointer is set to the container "struct epitem" */

wait_queue_t wait; / Wait queue item that will be linked to the target file wait queue head. /

wait_queue_head_t *whead;/The wait queue head that linked the "wait" wait queue item */

};//

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
epoll是一个在Linux内核中提供的I/O事件通知机制,采用了事件驱动的方式,用于高效处理大量的并发连接。它与select和poll相比有以下区别: 1. 底层实现epoll在内核中使用红黑树(红黑树是一种自平衡的叉搜索树)来存储和管理文件描述符,以及相应的事件。而select和poll则是通过遍历一个事件集合进行查询。 2. 打开的文件描述符数量限制:select和poll都将所有的文件描述符拷贝到内核空间中,因此有一个最大限制值(FD_SETSIZE),默认为1024(可以通过修改宏定义来改变)。而epoll没有这个限制,它采用事件驱动的方式,在注册的文件描述符上有事件发生时才进行通知,因此没有限制。 3. 效率:由于epoll采用事件驱动的方式,只有在有事件发生时才进行通知,因此能够大大提高效率,减少了遍历文件描述符的开销。而select和poll则在调用时需要遍历整个事件集合,效率较低。 4. 内存拷贝:select和poll在每次调用时都需要将所有监视的文件描述符集合拷贝到内核中,而epoll只需要在开始时注册,并且不需要拷贝。 5. 高并发支持:由于epoll采用事件驱动的方式,能够更好地处理大量并发连接。而select和poll则在大量文件描述符时会有性能下降的问题。 综上所述,epoll可以更高效地处理大量并发连接,并且没有文件描述符数量限制,相比之下select和poll的性能较低,且有文件描述符数量限制。

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值