网络编程实战
盛延敏
前大众点评云平台首席架构师
44207 人已学习
新⼈⾸单¥59
登录后,你可以任选4讲全文学习
课程目录
已完结/共 40 讲
网络编程实战
15
15
1.0x
00:00/00:00
登录|注册

29 | 渐入佳境:使用epoll和多线程模型

onMessage函数处理注意事项
边缘触发和条件触发的理解
epoll的性能优势
程序框架切换到epoll版本
边缘触发 vs. 条件触发
就绪列表
事件集合
服务器端epoll_wait处理
telnet客户端连接
服务器启动
回调函数运行在子反应堆线程中
缓冲区对象buffer
TCP服务器样例代码
样例程序修改
CMakeLists.txt配置
event_loop_init_with_name函数
epoll的性能优势
epoll vs. poll
思考题
总结
epoll的性能分析
样例程序结果
样例程序
如何切换到epoll
前言
渐入佳境:使用epoll和多线程模型

该思维导图由 AI 生成,仅供参考

你好,我是盛延敏,这里是网络编程实战第 29 讲,欢迎回来。
在前面的第 27 讲和第 28 讲中,我介绍了基于 poll 事件分发的 reactor 反应堆模式,以及主从反应堆模式。我们知道,和 poll 相比,Linux 提供的 epoll 是一种更为高效的事件分发机制。在这一讲里,我们将切换到 epoll 实现的主从反应堆模式,并且分析一下为什么 epoll 的性能会强于 poll 等传统的事件分发机制。

如何切换到 epoll

我已经将所有的代码已经放置到GitHub上,你可以自行查看或下载。
我们的网络编程框架是可以同时支持 poll 和 epoll 机制的,那么如何开启 epoll 的支持呢?
lib/event_loop.c 文件的 event_loop_init_with_name 函数是关键,可以看到,这里是通过宏 EPOLL_ENABLE 来决定是使用 epoll 还是 poll 的。
struct event_loop *event_loop_init_with_name(char *thread_name) {
...
#ifdef EPOLL_ENABLE
yolanda_msgx("set epoll as dispatcher, %s", eventLoop->thread_name);
eventLoop->eventDispatcher = &epoll_dispatcher;
#else
yolanda_msgx("set poll as dispatcher, %s", eventLoop->thread_name);
eventLoop->eventDispatcher = &poll_dispatcher;
#endif
eventLoop->event_dispatcher_data = eventLoop->eventDispatcher->init(eventLoop);
...
}
在根目录下的 CMakeLists.txt 文件里,引入 CheckSymbolExists,如果系统里有 epoll_create 函数和 sys/epoll.h,就自动开启 EPOLL_ENABLE。如果没有,EPOLL_ENABLE 就不会开启,自动使用 poll 作为默认的事件分发机制。
确认放弃笔记?
放弃后所记笔记将不保留。
新功能上线,你的历史笔记已初始化为私密笔记,是否一键批量公开?
批量公开的笔记不会为你同步至部落
公开
同步至部落
取消
完成
0/2000
荧光笔
直线
曲线
笔记
复制
AI
  • 深入了解
  • 翻译
    • 英语
    • 中文简体
    • 中文繁体
    • 法语
    • 德语
    • 日语
    • 韩语
    • 俄语
    • 西班牙语
    • 阿拉伯语
  • 解释
  • 总结

本文深入介绍了如何使用epoll和多线程模型实现高效的网络编程。作者首先展示了如何切换到epoll,并给出了一个样例程序,演示了事件分发机制从poll切换到epoll的过程。文章强调了epoll相对于poll和select的性能优势,主要体现在事件集合和就绪列表的处理上。此外,文章还详细解释了边缘触发和条件触发的区别,并提出了两道思考题,引发读者对这些概念的深入思考。 总的来说,本文通过实例和性能分析,全面展示了epoll在高性能网络编程中的重要性和优势,对于想要深入了解网络编程技术的读者来说,是一篇非常有价值的文章。

仅可试看部分内容,如需阅读全部内容,请付费购买文章所属专栏
《网络编程实战》
新⼈⾸单¥59
立即购买
登录 后留言

全部留言(22)

  • 最新
  • 精选
  • 沉淀的梦想
    在ET的情况下,write ready notification只会在套接字可写的时候通知一次的话,那个时候应用还没准备好数据,等到应用准备好数据时,却又没有通知了,会不会导致数据滞留发不出去?这种情况是怎么解决的呢?

    作者回复: 你可以再次注册这个write ready的事件啊,不是说只能注册一次就结束了,而是你注册了一次,它就通知你一次;而LT的情况下,可能你注册了一次,它通知你好多次。

    2019-10-15
    19
  • LiYanbin
    源代码看起来有点花了点时间,将这部分的代码从抽离了出来,便于大家跟踪代码理解,同时写了简单的makefile。代码地址:https://github.com/kevinrsa/epoll_server_multithreads 。如有不妥,联系删除

    作者回复: makefile写得不错:)

    2020-01-29
    14
  •  JJ
    边缘条件,当套接字缓冲区可写,会不断触发ready notification事件,不是应该条件触发才是这样吗?

    作者回复: 笔误,已经让编辑勘误了,感谢指正。

    2019-10-14
    2
    7
  • rongyefeng
    如果应用程序只读取了 50 个字节,边缘触发就会陷入等待; 这里的陷入等待是什么意思呢

    作者回复: 不会再继续发送read_notification事件,必须等所有的100个字节被读完,才会发送下一个read_notification事件。

    2020-05-22
    2
    5
  • 张三说
    老师,一直没搞懂ET和LT的性能区别,仅仅因为LT会多提醒一些次数就与ET相差明显的性能吗?一直很纠结这个问题

    作者回复: 有没有跑例子程序呢?其实不用纠结,最新的测试表明,两者差别其实没有那么大。但是非要比一个差距的话,ET还是效率好一些,但是对应用程序开发者的要求高一些。

    2019-12-13
    2
    5
  • 流浪地球
    细读了下老师git上的代码,套接字都是设置为非阻塞模式的,但并没有对返回值做判断处理,看上去好像是阻塞式的用法,求解?

    作者回复: 可能是考虑不周,有可能的话麻烦提一个MR或者issue,大家一起来改。

    2019-10-17
    5
  • 郑祖煌
    27章以及以后源代码的难度提升了一个等级了。看了相当吃力呀。

    作者回复: 多读两遍会好很多

    2020-07-08
    2
    1
  • Joker
    老师,这个就绪列表是建立在事件集合之上的对吧。

    作者回复: 是的,是所有感兴趣的事件集合。

    2020-04-16
    1
  • ray
    老师好, 针对第2题,目前想到onMessage函数应该要注意,如果当前程序无法处理该通知,应该要想办法再次注册该事件。 只是具体程序实现就不知道应该怎么写了,可能还要请老师说明一下 哈哈XD 谢谢老师^^

    作者回复: 当前的实现并不会主动把I/O读写事件从事件通道上摘除哦,所以并不需要重新注册该事件,onMessage就是一个简单的报文解析函数,所要做到的就是在条件触发情况下读完所有的字节,避免不断的再次被事件驱动。

    2020-04-12
    2
    1
  • 丁小明
    为什么 socket已经有缓冲区了,应用层还要缓冲区呢,比如发送,socket也会合并发送

    作者回复: 很简单,应用层需要对接收到的byte字节流进行编解码,为了方便,在应用层进行缓冲,之后进行编解码的操作,再送给业务逻辑层来处理。

    2020-03-10
    2
    1
收起评论
显示
设置
留言
22
收藏
沉浸
阅读
分享
手机端
快捷键
回顶部