问题标签 [epollet]
For questions regarding programming in ECMAScript (JavaScript/JS) and its various dialects/implementations (excluding ActionScript). Note JavaScript is NOT the same as Java! Please include all relevant tags on your question; e.g., [node.js], [jquery], [json], [reactjs], [angular], [ember.js], [vue.js], [typescript], [svelte], etc.
linux - EPOLLET 模式下的 Epoll 在从套接字读取之前返回 2 EPOLLIN
epoll 手册页说,如果没有进行读取,使用 EPOLLET(边缘触发)注册的 fd 不应通知两次 EPOLLIN。
因此,在 EPOLLIN 之后,您需要在 epoll_wait 能够在新数据上返回新的 EPOLLIN 之前清空缓冲区。
但是,我在使用这种方法时遇到了问题,因为我看到未触及的 fd 的重复 EPOLLIN 事件。
这是 strace 输出,0x200 是 EPOLLRDHUP,尚未在我的 glibc 头文件中定义,但在内核中定义。
因此,在添加 fd 编号 9 之后,我在接收文件描述符之前确实收到了 2 个连续的 EPOLLIN 事件,系统调用跟踪显示了我如何在读取之前删除 fd,但它应该只发生一次,每个事件一个。
所以要么我没有正确阅读手册页,要么现在这里有什么工作。
c - 与 epoll 一起使用时的非阻塞套接字接收问题
我有一个问题:有时(不定期)recv 返回-1
并且在模式下errno == EAGAIN
使用。一段代码:epoll
edge-triggered
startup(&port)
创建非阻塞套接字,与端口绑定等。我的脚本发送以下数据:
GET /connect?id=1&secret=1 HTTP/1.0\r\n\r\n
但有时会在此函数中recv
返回-1
(在内部调用accept_request
):
正如 epoll 手册页所写,我必须读/写直到我得到EAGAIN
,但我已经明白了!我确定缓冲区不是空的。我做错了什么?
UPD:我发现了一件有趣的事情:当这种情况发生时,我在我的代码中反复使用,我sleep(1)
得到recc(...)
了我期望的数据!这是一个肮脏的把戏。有没有更优雅的方法来解决这个问题?
linux - 如何使用 epoll_select 和 EPOLLET 读取多个文件描述符?
人epoll:
想象一下我们有两个 fd:第一个是被动的,数据仅有时可用,第二个是主动的,数据有时不可用。
epoll_wait 返回我们可以读取两者。我们在循环中读取{第一个,而不是第二个}(没有调用 epoll_wait 因为它可能会在数据仍然可用时突然阻塞)。
现在第一个文件描述符在读取时返回 EAGAIN。
该怎么办?
- 如果我们继续在循环中读取第二个 fd(不调用 epoll_wait),我们可能会错过第一个 fd 上的数据可用。它只会在没有 EAGAIN 的情况下阅读和阅读。
- 如果我们在每次从第二个 fd 读取之前“咨询” epoll_wait,则 epoll_wait 可能会因为前一次调用没有任何更改而突然阻塞(数据在第一个 FD 上仍然不可用,但在第二个 FD 上仍然可用)。
如何继续处理第二个 FD,但又不会忘记第一个 FD?
更新:又发现了一件事:man epoll_wait:
有了这个,即使没有事件,我也可以枚举 FD 的事件。
epoll - 使用边缘触发的 epoll,我应该循环发送吗?
我正在使用 epoll 编写媒体服务器。fds 都设置为非阻塞,我正在使用边缘触发事件。我知道对于 EPOLLIN,我需要循环读取 fd,直到返回 EAGAIN。但是写作呢?
当我想写数据时,我将数据排队并在 fd 上设置 EPOLLOUT|EPOLLIN|EPOLLET。当 EPOLLOUT 事件发生时,我一次性写入整个队列缓冲区:
如果 n > 0 && n < buf_len 我只是重置 EPOLLOUT 并返回。我没有看到循环发送的意义(我认为 epoll 的手册页暗示了这一点)。似乎 send 已经表明它已经接受了所有它可以并且如果立即调用将返回 EAGAIN。
在这里消除系统调用是最有效的途径吗?
c++ - epoll:丢失一些 EPOLLOUT 事件?
这是我的服务器的样子:
-WorkerThread(s):
- 调用 epoll_wait,接受连接,设置 fd 非阻塞(EPOLLIN | EPOLLOUT | EPOLLET | EPOLLRDHUP)
- 在 EPOLLIN 事件上调用 recv 直到 EAGAIN 并将所有数据推送到全局 RecvBuffer(pthread_mutex 同步)
- 在 EPOLLOUT 事件上:访问全局 SendBuffer,如果当前准备好的 fd 有数据要发送,则执行此操作(在 while 循环中,直到 EAGAIN 或直到发送所有数据;发送整个数据包时,从 SendBuffer 中弹出)
-IOThread(s)
- 从全局 RecvBuffer 获取数据,处理它们
- 通过首先尝试立即调用 send 来发送响应。如果没有发送所有数据,则将其余数据推送到全局 SendBuffer 以从 WorkerThread 发送)
问题是,该服务器没有发送所有排队的数据(它们留在 SendBuffer 中),并且“未发送”数据的数量随着客户端数量的增加而增长。为了测试我只使用 1 个工作线程和 1 个 iothread,但如果我使用更多似乎没有任何区别。访问全局缓冲区受 pthread_mutex 保护。此外,我的响应数据大小为 130k 字节(至少需要 3 个发送调用才能发送这么多数据)。另一方面是使用阻塞套接字的 Windows 客户端。
非常感谢!乔丹
编辑:
是的,默认情况下我正在等待 EPOLLOUT 事件,即使我没有要发送的内容。为了实现简单和手册页指南,我这样做了。另外,我对它的理解是这样的:
即使我当时“错过” EPOLLOUT 事件我不想发送任何东西也没问题,因为当我想发送数据时,我会调用 send 直到 EAGAIN 和 EPOLLOUT 应该在未来被触发(而且大部分时间)
现在我修改了代码以在 IN/OUT 事件之间切换:
接受时:
发送完所有数据后:
当我通过在 IOThread 中调用 send 到达 EAGAIN 时:
..我得到同样的行为。另外,我尝试删除 EPOLLET 标志,但没有任何改变
一个问题:带有 EPOLL_CTL_MOD 标志的 epoll_ctl 是替换事件成员还是只是用给定的参数对它进行 OR 运算?
EDIT3:更新了 IOThread 函数以连续发送,直到所有数据都发送完毕,或者直到 EAGAIN。即使我发送了所有数据,我也尝试发送,但大多数时候我在非套接字上得到 errno 88 套接字操作
EDIT4:我修复了“发送代码”中的一些错误,因此我现在没有收到任何未发送的排队数据。但是,我没有收到应有的数据:)) 最多的“错过”(未收到)数据我发送完成后客户端立即调用recv时获取,并且随着客户端数量的增加而增长。当我在客户端的发送和接收调用之间设置 2 秒延迟(阻塞调用)时,我不会丢失服务器上的少量数据,具体取决于正在运行的客户端数量(客户端测试代码包括简单的 for 循环,其中包含 1 个发送和 1 个接收调用)再次尝试使用和不使用 ET 模式。下面是更新的 WorkerThread 函数,它负责接收数据。@Admins/Mods 也许我现在应该打开新主题,因为问题有点不同?
c - C:使用epoll ET的数据转发服务器填满发送缓冲区
我有以下情况。我的服务器从远程服务器(fd_server)接收数据并将其转发给客户端(fd_client)。我正在使用边缘触发的 epoll,因此我可以处理多个客户端和多个服务器连接。
程序:
- 客户端连接到服务器。
- 我的服务器连接到远程服务器并请求数据。
- 远程服务器响应,我的服务器将数据转发给客户端。
细节:
在我的服务器连接到远程服务器后,fd_server 被添加到带有 EPOLLIN 标志的 epoll 控件中。服务器等待事件。
当 epoll_wait 返回 fd_server 可读时,我将进入下面显示的以下循环。
经过一些读/写后,我的 sctp_sendmsg 返回 EAGAIN,这意味着 sctp 发送缓冲区已满。我应该如何处理这种情况而不会丢失我已经从 fd_server 套接字读取的数据?
有没有办法事先知道,我可以发送多少数据,所以我只读取正确的数量?
c - epoll(EPOLLET)取决于读取字节数?
我在边缘触发模式下使用 epoll。为了避免饥饿,代码一次从一个套接字读取 MAX_FREAD_LENGTH 个字节。稍后组装碎片,直到出现 EOL。我注意到当 MAX_FREAD_LENGTH 很小时,epoll 卡住了。我认为它应该适用于任何大小的读取块。它适用于 512 字节,但有时会挂起(意味着没有 EPOLLIN 事件)。如果我增加 MAX_FREAD_LENGTH 它变得更加稳定。我该如何解决这个问题?
非常感谢您考虑我的问题!
EPOLL 初始化
注册网络事件:
处理一个网络事件
编辑:
我忘了提,epoll 在一个单独的线程中运行,而不是其他部分
multithreading - 具有边缘触发、单次和多线程的 epoll
这是一个关于这个答案的问题:https : //stackoverflow.com/a/14241095/2332808 (会评论它,但新创建的帐户显然不能,对于噪音感到抱歉。很难找到关于 epollet/multithreading 的资源.. .)
它建议使用 epoll 如下:
epoll_ctl()
激活通知(如果EPOLLONESHOT
使用则重新激活)。- 系统输入://
read()
循环直到出错。recv()
accept()
EAGAIN
epoll_wait()
接收通知。
epoll_wait()
但是,假设在同一个 epollfd 上有多个线程,如果它在您完成读取之前接收到更多数据(例如,最终两个线程处理同一个 fd )
即使你把事情转过来read()
直到EAGAIN
,epoll_ctl()
然后read()
再次打电话来检查仍然没有任何东西(以避免在最后一次阅读和 之间你会收到一些东西的比赛epoll_ctl()
)......
但是仍然不能保证您在 之后实际上不会收到任何东西,epoll_ctl()
并且最后一次read()
检查和另一个线程都被唤醒,再次在同一个 fd 上工作......
我想每个 fd 都有一个锁是一个可以接受的解决方案,但是在边缘触发模式下“批准”使用 epoll 并且多个线程在同一个 epollfd 上轮询?
c++ - epoll_wait() > 1 是否只有 1 个套接字和 1 个事件——EPOLLIN?
假设我 epoll_create1() 并且只对 EPOLLIN 感兴趣 | 用于 1 个插座的 EPOLLET。
我是否有可能为该套接字获得 epoll_wait() > 1(假设 timeout=-1)并且事件是 EPOLLIN?
或者即使有多个数据包,epoll_wait() 也会返回 1(假设分散在几秒钟内,我在 epoll_wait 循环中故意暂停程序)?
提前致谢。
linux - Epoll TCP edge-triggered necessity of last read(2) call
Given a nonblocking TCP socket, if the call
returns a value < bufLen
, is it safe to then wait for an edge-triggered EPOLLIN event? Or must I call read
again to ensure it's zero or EAGAIN?
In my testing, everything stays working when I remove the last call, I just want to know if it's guaranteed anywhere, or by the Linux source code, and if I can get rid of the extra call.