epoll之一:epoll的原理

8 篇文章 0 订阅
6 篇文章 0 订阅

之前 我写过一篇博客IO复用之select poll epoll 函数,大概介绍了一下epoll和select,poll的一些区别,接下来要 从原理剖析epoll的强大的原因

select和poll的工作机制

在某一时刻,进程收集有事件连接时,大部分的连接是没有发生事件,但是 select和poll的工作机制,在 每次收集事件 的 时候,都把全部 的 连接的 套接字传给操作系统(这首先就是用户态内存到内核态内存的大量复制),同时由操作系统内核寻找这些连接上有没有事件发生,将是一个很耗时的事情,所以 select和epoll只能处理几千个并发连接(也受到操作系统文件描述符的限制)。

epoll的工作机制

首先epoll在Linux内核中申请了一个 简易的文件系统,将一个 poll或select调用分成了3个部分:

  • 调用epoll_create建立1个epoll对象(在epoll文件系统中 给这个 句柄 分配资源)
  • 调用epoll_ctlepoll添加大量的连接套接字
  • 调用epoll_wait收集发生事件 的连接。

这样,只需要在进程启动的时候建立 1个epoll对象,并在需要的 时候向他添加或删除连接 就可以,在实际收集事件时,epoll_wait的效率会非常的高,调用epoll_wait时并没有向它传递全部的 连接,内核也不需要遍历全部的 连接

详解epoll_create方法

当一个进程调用epoll_create方法时,Linux内核会创建 一个eventpoll结构体,这个 结构体中有两个 成员与epoll使用 的 方式密切相关

struct eventpoll{
 /*红黑树的根节点,这颗树存储着所有添加到epoll的事件,也就是这个epoll监控 的事件*/
 struct rb_root rbr;

 // 双向链表rallist保存着将要 通过 epoll_wait返回给用户的、满足条件的事件 
 struct list_head rdllist;
 ...
}

每一个epoll对象都有一个独立的eventpoll结构体,这个 结构体会在内核 空间创造独立 的内存,用于存储使用epoll_ctl方法向epoll对象添加 进来的事件。这些事件都会 挂在rbr红黑树中,这样重复添加的事件就 可以通过红黑树而高效地识别出来。所有添加到epoll的事件都会与设备(如网卡)驱动程序建立 回调关系,也就是说,相应的事件发生时会调用这里的回调方法。这个 回调的方法 在内核叫做ep_poll_callback,它会把这样的事件放在上面的rdllist双向链表中。

在 epoll中,对于每个 事件 都会 建立一个epitem结构体

struct epitem
{
    //红黑树节点
    struct rb_node rbn;
    //双链 表节点
    struct list_head rdllink;
    //事件 句柄信息 
    struct epoll_filefd ffd;
    //指向其所属的eventpoll对象
    struct  eventpoll *ep;
    // 期待 的事件类型
    struct epoll_event  event;
}

这里 包含 每一个事件对应着的信息,当 调用epoll_wait检查是否有 发生事件的连接时,只是检查eventpoll对象中的rdllist双向链表是否有epitem元素而已,如果rdllist链表不为空,则把这里的事件复制到用户态 的 内存中,同时将事件数量返回给用户。

  • 0
    点赞
  • 1
    收藏
    觉得还不错? 一键收藏
  • 打赏
    打赏
  • 0
    评论

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

程序猿阿三

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

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

余额充值