Linux内核源码分析---epoll 系统调用

int select(int nfds, fd_set *readfds, fd_set *writefds, fd_set *exceptfds, struct timeval *timeout);

select:只能监控 FD_SETSIZE 个链接,libc 里这个数量设置的很小,需要在每次调用时重新构建fd_set

int poll (struct pollfd *fds, unsigned int nfds, int timeout);

pollfd 的结构体定义了一个events和一个revents,它们也是两个位图,每一位代表一个事件,events 代表监控的事件,revents 代表返回时具有的事件,监控事件和返回事件分离的设计让我们不用像使用 select 一样,每次都重新构建fd_set

poll:尽管没有链接数的限制,也就是说可以监控 RLIMIT_NOFILE 个链接, 但是每一次都要对所有监控链接从头到尾的扫描,速度O(n),这也降低了性能;
在这两个系统调用使用时,内核与用户空间通过内存复制来进行消息传递,进一步降低性能。

select比poll更加通用,一些unix系统不支持poll

epoll 没有 selectpoll 的限制, 可以 O(1) 时间处理操作, 内核与用户空间通过 mmap 来进行消息传递,又进一步加快了速度。

在用户空间中管理所有事儿,并且我们在每次调用时都要发送所有关心的文件描述符到内核,如果我们想添加一个新的文件描述符,就要将它加到集合中并重新调用 select 和 poll。

与 epoll 相关的系统调用有:

epoll_create:在内核中创建一个上下文 epoll instance
epoll_create1:同上
epoll_ctl:用来在 epoll instance 上添加、删除被监控的文件描述符(file descriptor);
epoll_wait:获取有事件发生的文件描述符,当没有时会一直被阻塞;

当文件描述符被加入后,事件通知的方式有两种:

level triggered:当你未及时处理时,一个事件会持续通知,直到你处理完毕;
edge triggered:一个事件只通知一次;

epoll 在内核中维护文件描述符上下文,所以我们不用每次调用都向内核复制文件描述符列表
epoll 中,我们不需要遍历所有我们监控的 fd,只需要遍历已经准备好的那些(特定事件)

epoll 数据结构

epoll 数据结构主要有 epoll 事件 epoll_event,监听系统本身 eventpoll ,被监听的对象epitem,以及被监听对象在设备等待队列中的存在形式 eppoll_entry

在这里插入图片描述

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

监听系统本身 eventpoll
在这里插入图片描述

被监听的对象epitem
在这里插入图片描述

epitem 在设备等待队列中存在 eppoll_entry
在这里插入图片描述

epoll 内核实现

epoll_create 系统调用内核实现
系统调用 epoll_create() 会创建一个 epoll实例并返回该实例对应的文件描述符 fd。在内核中,每个epoll实例会和一个struct eventpoll类型的对象一一对应,该对象是epoll的核心。此对象包含红黑树 rbr用于存储epitem对象,等待队列wg,就绪链表rdllist等。构建 file 对象,同时将 eventpoll 对象ep挂到file对象的 private_data 对象上面。

在这里插入图片描述
在这里插入图片描述

1.首先创建一个struct eventpoll对象;
2.分配一个未使用的文件描述符;
3.创建一个struct file对象,将file中的struct file_operations *f_op设置为全局变量eventpoll_fops,将void *private指向刚创建的eventpoll对象ep
4.然后设置eventpoll中的file指针;
5.最后将文件描述符添加到当前进程的文件描述符表中,并返回给用户。

epoll_ctl系统调用内核实现
构建 epitem 挂到 epoll 红黑树上;构建 eppoll_entry 挂到设备等待队列,其中eppoll_entry包含回调函数 ep_poll_callback 和对应的 epitem
在这里插入图片描述

epoll_wait系统调用内核实现
在这里插入图片描述

如何使用epoll系统调用
深入io到epoll与linux内核系统调用
IO多路复用模型以及select、poll、epoll系统调用
一文带你了解Linux内核epoll实现原理与机制

  • 8
    点赞
  • 17
    收藏
    觉得还不错? 一键收藏
  • 打赏
    打赏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

打赏作者

飞大圣

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

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

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

打赏作者

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

抵扣说明:

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

余额充值