在上一篇文章 Linux epoll 源码分析 2 中,我们分析了 epoll_ctl 的 ep_insert 方法,在这里我们继续看下 ep_remove 和 ep_modify 方法。
我们先看下 ep_remove 方法
// fs/eventpoll.c static int ep_remove(struct eventpoll *ep, struct epitem *epi) { ... struct file *file = epi->ffd.file; ... // 将epitem从tcp socket的事件变动通知队列中移除 ep_unregister_pollwait(ep, epi); ... // 从eventpoll中的红黑树数据结构中移除 rb_erase_cached(&epi->rbn, &ep->rbr); ... // 如果epitem在eventpoll的rdllist队列中,也移除 if (ep_is_linked(&epi->rdllink)) list_del_init(&epi->rdllink); ... return 0; }
再看下ep_modify 方法
static int ep_modify(struct eventpoll *ep, struct epitem *epi, struct epoll_event *event) { ... epi->event.events = event->events; epi->event.data = event->data; ... revents = ep_item_poll(epi, &pt, 1); ... if (revents & event->events) ... if (!ep_is_linked(&epi->rdllink)) { list_add_tail(&epi->rdllink, &ep->rdllist); ... if (waitqueue_active(&ep->wq)) wake_up_locked(&ep->wq); ... } spin_unlock_irq(&ep->lock); } ... return 0; }
该方法的逻辑和ep_insert方法里的逻辑比较像,它先覆盖epitem中epoll_event的旧值,然后检查该文件当前已经就绪的事件,如果这些事件中有我们感兴趣的事件,则把epitem放到eventpoll的rdllist队列中,最后通知因调用epoll_wait堵塞的线程,它们可以继续执行了。
至此,epoll的所有逻辑都已讲完。
有关tcp在何种情况下,会通知给epoll何种事件,我们会在其他文章中详细讲解。
本文分享自 Linux内核及JVM底层相关技术研究 微信公众号,前往查看
如有侵权,请联系 cloudcommunity@tencent.com 删除。
本文参与 腾讯云自媒体同步曝光计划 ,欢迎热爱写作的你一起参与!