问题标签 [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.

0 投票
3 回答
4938 浏览

linux - EPOLLET 模式下的 Epoll 在从套接字读取之前返回 2 EPOLLIN

epoll 手册页说,如果没有进行读取,使用 EPOLLET(边缘触发)注册的 fd 不应通知两次 EPOLLIN。
因此,在 EPOLLIN 之后,您需要在 epoll_wait 能够在新数据上返回新的 EPOLLIN 之前清空缓冲区。

但是,我在使用这种方法时遇到了问题,因为我看到未触及的 fd 的重复 EPOLLIN 事件。
这是 strace 输出,0x200 是 EPOLLRDHUP,尚未在我的 glibc 头文件中定义,但在内核中定义。

因此,在添加 fd 编号 9 之后,我在接收文件描述符之前确实收到了 2 个连续的 EPOLLIN 事件,系统调用跟踪显示了我如何在读取之前删除 fd,但它应该只发生一次,每个事件一个。
所以要么我没有正确阅读手册页,要么现在这里有什么工作。

0 投票
1 回答
5393 浏览

c - 与 epoll 一起使用时的非阻塞套接字接收问题

我有一个问题:有时(不定期)recv 返回-1并且在模式下errno == EAGAIN使用。一段代码:epolledge-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(...)了我期望的数据!这是一个肮脏的把戏。有没有更优雅的方法来解决这个问题?

0 投票
1 回答
1305 浏览

linux - 如何使用 epoll_select 和 EPOLLET 读取多个文件描述符?

人epoll:

想象一下我们有两个 fd:第一个是被动的,数据仅有时可用,第二个是主动的,数据有时不可用。

epoll_wait 返回我们可以读取两者。我们在循环中读取{第一个,而不是第二个}(没有调用 epoll_wait 因为它可能会在数据仍然可用时突然阻塞)。

现在第一个文件描述符在读取时返回 EAGAIN。

该怎么办?

  1. 如果我们继续在循环中读取第二个 fd(不调用 epoll_wait),我们可能会错过第一个 fd 上的数据可用。它只会在没有 EAGAIN 的情况下阅读和阅读。
  2. 如果我们在每次从第二个 fd 读取之前“咨询” epoll_wait,则 epoll_wait 可能会因为前一次调用没有任何更改而突然阻塞(数据在第一个 FD 上仍然不可用,但在第二个 FD 上仍然可用)。

如何继续处理第二个 FD,但又不会忘记第一个 FD?

更新:又发现了一件事:man epoll_wait:

有了这个,即使没有事件,我也可以枚举 FD 的事件。

0 投票
2 回答
2483 浏览

epoll - 使用边缘触发的 epoll,我应该循环发送吗?

我正在使用 epoll 编写媒体服务器。fds 都设置为非阻塞,我正在使用边缘触发事件。我知道对于 EPOLLIN,我需要循环读取 fd,直到返回 EAGAIN。但是写作呢?

当我想写数据时,我将数据排队并在 fd 上设置 EPOLLOUT|EPOLLIN|EPOLLET。当 EPOLLOUT 事件发生时,我一次性写入整个队列缓冲区:

如果 n > 0 && n < buf_len 我只是重置 EPOLLOUT 并返回。我没有看到循环发送的意义(我认为 epoll 的手册页暗示了这一点)。似乎 send 已经表明它已经接受了所有它可以并且如果立即调用将返回 EAGAIN。

在这里消除系统调用是最有效的途径吗?

0 投票
1 回答
5729 浏览

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 也许我现在应该打开新主题,因为问题有点不同?

0 投票
1 回答
872 浏览

c - C:使用epoll ET的数据转发服务器填满发送缓冲区

我有以下情况。我的服务器从远程服务器(fd_server)接收数据并将其转发给客户端(fd_client)。我正在使用边缘触发的 epoll,因此我可以处理多个客户端和多个服务器连接。

程序:

  1. 客户端连接到服务器。
  2. 我的服务器连接到远程服务器并请求数据。
  3. 远程服务器响应,我的服务器将数据转发给客户端。

细节:

在我的服务器连接到远程服务器后,fd_server 被添加到带有 EPOLLIN 标志的 epoll 控件中。服务器等待事件。

当 epoll_wait 返回 fd_server 可读时,我将进入下面显示的以下循环。

经过一些读/写后,我的 sctp_sendmsg 返回 EAGAIN,这意味着 sctp 发送缓冲区已满。我应该如何处理这种情况而不会丢失我已经从 fd_server 套接字读取的数据?

有没有办法事先知道,我可以发送多少数据,所以我只读取正确的数量?

0 投票
1 回答
1679 浏览

c - epoll(EPOLLET)取决于读取字节数?

我在边缘触发模式下使用 epoll。为了避免饥饿,代码一次从一个套接字读取 MAX_FREAD_LENGTH 个字节。稍后组装碎片,直到出现 EOL。我注意到当 MAX_FREAD_LENGTH 很小时,epoll 卡住了。我认为它应该适用于任何大小的读取块。它适用于 512 字节,但有时会挂起(意味着没有 EPOLLIN 事件)。如果我增加 MAX_FREAD_LENGTH 它变得更加稳定。我该如何解决这个问题?

非常感谢您考虑我的问题!

EPOLL 初始化

注册网络事件:

处理一个网络事件

编辑:

我忘了提,epoll 在一个单独的线程中运行,而不是其他部分

0 投票
1 回答
1777 浏览

multithreading - 具有边缘触发、单次和多线程的 epoll

这是一个关于这个答案的问题:https : //stackoverflow.com/a/14241095/2332808 (会评论它,但新创建的帐户显然不能,对于噪音感到抱歉。很难找到关于 epollet/multithreading 的资源.. .)

它建议使用 epoll 如下:

  1. epoll_ctl()激活通知(如果EPOLLONESHOT使用则重新激活)。
  2. 系统输入://read()循环直到出错。recv()accept()EAGAIN
  3. epoll_wait()接收通知。

epoll_wait()但是,假设在同一个 epollfd 上有多个线程,如果它在您完成读取之前接收到更多数据(例如,最终两个线程处理同一个 fd )

即使你把事情转过来read()直到EAGAINepoll_ctl()然后read()再次打电话来检查仍然没有任何东西(以避免在最后一次阅读和 之间你会收到一些东西的比赛epoll_ctl())......

但是仍然不能保证您在 之后实际上不会收到任何东西,epoll_ctl()并且最后一次read()检查和另一个线程都被唤醒,再次在同一个 fd 上工作......

我想每个 fd 都有一个锁是一个可以接受的解决方案,但是在边缘触发模式下“批准”使用 epoll 并且多个线程在同一个 epollfd 上轮询?

0 投票
2 回答
461 浏览

c++ - epoll_wait() > 1 是否只有 1 个套接字和 1 个事件——EPOLLIN?

假设我 epoll_create1() 并且只对 EPOLLIN 感兴趣 | 用于 1 个插座的 EPOLLET。

我是否有可能为该套接字获得 epoll_wait() > 1(假设 timeout=-1)并且事件是 EPOLLIN?

或者即使有多个数据包,epoll_wait() 也会返回 1(假设分散在几秒钟内,我在 epoll_wait 循环中故意暂停程序)?

提前致谢。

0 投票
2 回答
2620 浏览

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.