EPOLL-EPOLL_WAIT返回多次

本文探讨了在使用EPOLL进行数据接收时遇到的问题:当客户端发送大量数据时,由于处理延迟导致数据混乱或接收不完全。文章提供了一种通过在处理事件前移除并事后重新注册套接字的方法来解决问题,并讨论了该方法可能引发的新问题及其解决方案。
客户端发送1M数据,需要保存中间状态,接收多次,在EPOLL_WAIT返回后,接收线程还在处理上次epoll_wait返回的事件中,这时epoll_wait又返回事件了,导致另外一个线程也开始接收同一个客户端同一次发送的数据,导致客户端发送的数据保存乱掉,若数据的最前面携带数据的长度的话,就会导致数据永远无法接收完毕。解决这个问题我用的方法是在接收到epoll_wait返回的某个套接字的事件时,从epoll fd中使用epoll_ctl del删除此套接字的注册,然后处理完毕此套接字的事件后又重新注册套接字事件。但是这时又出现另外一个问题,就是epoll_ctl add时有时候会失败,导致套接字未被注册上,导致这个套接字的事件永远无法再被接收。目前还没有查明为什么会注册失败,注册失败后,连续注册三次的规避措施也会失败,可打印注册失败原因,errno值来确定失败原因,再调整代码。
### SyS_epoll_wait 和 do_epoll_wait 的区别及用法 #### 函数定义与调用层次结构 `SyS_epoll_wait` 是系统调用接口函数,位于用户空间和内核之间的边界上。当应用程序通过 `epoll_wait()` 调用时,实际上是在调用这个系统调用入口点[^1]。 ```c SYSCALL_DEFINE4(epoll_wait, int, epfd, struct epoll_event __user *, events, int, maxevents, int, timeout) { return do_epoll_wait(epfd, events, maxevents, timeout); } ``` `do_epoll_wait` 则是一个更底层的实现函数,在内核内部被多个地方调用。它负责处理实际的工作逻辑,包括等待事件的发生并返回给用户态程序[^2]。 #### 实现细节对比 - **参数传递** `SyS_epoll_wait` 接收来自用户的输入参数并通过验证后传入到 `do_epoll_wait` 中继续处理。这一步骤确保了安全性以及合法性检查[^3]。 - **上下文切换** 当进入 `SyS_epoll_wait` 后会触发一次从用户模式到核心模式的转换;而在完成工作之后再由 `do_epoll_wait` 返回结果前又会发生相反方向上的特权级变化[^4]。 - **错误处理机制** 如果在 `do_epoll_wait` 执行期间遇到任何异常情况,则会被捕获并将相应的错误码反馈回至 `SyS_epoll_wait`,最终呈现给应用层开发者作为诊断依据[^5]。 #### 使用场景说明 对于大多数开发人员来说,通常只需要关注如何正确地使用 `epoll_wait()` 进行高效的 I/O 多路复用操作即可,并不需要深入了解这两个具体函数的区别。然而理解它们之间关系有助于更好地掌握 Linux 内核工作机制及其性能优化原理[^6]。
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

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

余额充值