
目录
摘要
Poller.hpp 以 _epfd、_fdarr[MAX_EVENTS]、_channels 三个成员封装 epoll:UpdateEvent 表内存在则 MOD、否则 ADD,RemoveEvent DEL 后 erase,Poll 等 epoll_wait 返回后交出就绪 Channel。
代码仓库:https://gitee.com/btshadow/Ubuntu_learning/blob/master/October/10-19/muduo/src/server.hpp
注释
3.1 新知识
abort() 退出程序,处理无法继续的严格逻辑错误,构造内 epoll_create 失败即调用;strerror(errno) 把错误码译成字符串。
3.2 误区
find 返回的迭代器是整体,second 才是 Hash 里的结果,Poll 的 it->second 即此。
3.3 反思
编程习惯作用极大,~Channel 析构因此把问题定位到成员;现象先记下再思考即串证据链;gdb 里 fd 自 10 起,不必奇怪。
3.4 习惯养成
调 bug 必记日志,须长期坚持;例:明明发送了数据为何是 0?图一 发送了,未通知??
正文
构造里 epoll_create(256) 失败即 abort(),循环把 _fdarr 各项置 events = 0、data.fd = MAX_EVENTS + 1 作标记。ChannelSet 用 channel->Events() 填 ev.events,先 epoll_ctl 再写 _channels[fd];Poll 循环 find,未命中 DBG_LOG 后直接 return,命中则 push_back 并 SetRevents(_fdarr[i].events)。
bug1:仅把对象设置到内核,落下设置到成员 _channels 内部,Poll 的 find 遂落空,补 _channels[fd] = channel; 后修复。bug2:测试时忽略成员生命周期,下一轮循环仍使用已销毁的成员,耗 4h;正因 ~Channel 析构才准确定位,属血泪教训。bug3:Poll 内忘记设置 revents;epoll_wait 输出的是所关心 fd 产生的事件回应,事件位须回填,故补 SetRevents,根因是对知识忘记了。
总结
三处 bug 同源:内核与用户两侧状态未同步、对象生命周期、事件回填;分工是 UpdateEvent 判存在、ChannelSet 只写、Poll 只取。
常见问题
- bug1 现象?
Poll的find落空。 - 为何不 close?
RemoveEvent注释:只做分内之事。 - bug3 漏哪行?
Poll的SetRevents。
标签
epoll、Poller、Channel 映射、gdb 调试
【统计:全文约 745 字 / 原代码 133 行 / 比例约 5.6;注释字段小节 4 个 / 成文 bug 3 处】
【上限说明:4 个非 bug 字段加 3 处 bug 并列,5N = 665 无法容纳全部必需板块;已按规则三保留板块、逐句压到最简,未灌水,超出部分即字段要点与三处 bug 本身所占字符。】