标签: epollet

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

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

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

n = send ( fd, buf, buf_len, MSG_NOSIGNAL );
Run Code Online (Sandbox Code Playgroud)

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

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

epoll epollet

6
推荐指数
1
解决办法
2228
查看次数

TCP:何时生成EPOLLHUP?

另请参阅此问题,到目前为止尚未回答。

EPOLLHUP即使在man和内核文档中也有很多关于的困惑。人们似乎相信,当一个描述符轮询它返回本地关闭书写,即shutdown(SHUT_WR),即导致相同的呼叫EPOLLRDHUP 在对等。但这是不正确的,在我的实验中,我得到了EPOLLOUTEPOLLHUP之后没有得到shutdown(SHUT_WR)(是的,变得可写是违反直觉的,因为写作的一半是封闭的,但这不是问题的重点)。

这个很穷,因为它EPOLLHUP说到挂起发生在关联的文件描述符上时,而没有说“挂断”是什么意思-对方做了什么?发送了什么数据包?另一篇文章只是使事情更加混乱,对我来说似乎是完全错误的。

我的实验表明,EPOLLHUP一旦双向交换EOF(FIN数据包),即双方都发出,就到达了shutdown(SHUT_WR)。它与无关SHUT_RD,我从不称呼它。也与无关close。在数据包方面,我怀疑EPOLLHUP主机发送的FIN会引起确认,即终止发起方在4向关机握手的第3步中引发此事件,而对等方在第4步中引发(请参见此处))。如果得到确认,那就太好了,因为它填补了我一直在寻找的空白,即如何在不使用LINGER的情况下轮询非阻塞套接字以获得最终的确认。它是否正确?

(注意:我正在使用ET,但我认为与此无关)

示例代码和输出。

该代码在一个框架之中,我提取它的肉,用之外TcpSocket::createListenerTcpSocket::connectTcpSocket::accept,它做你所期望(这里没有显示)。

void registerFd(int pollFd, int fd, const char* description)
{
    epoll_event ev = {
        EPOLLIN | EPOLLOUT | EPOLLRDHUP | EPOLLET,
        const_cast<char*>(description) // union aggregate initialisation, initialises …
Run Code Online (Sandbox Code Playgroud)

linux epoll tcp linux-kernel epollet

6
推荐指数
1
解决办法
1143
查看次数

是否在不等待epoll_waiting时监视epoll事件

我对基于事件的编程很陌生。我正在尝试使用epoll边缘模式,该模式显然仅信号通知已准备好进行读/写的文件(而不是级别模式,该信号通知所有就绪文件,无论是否已经就绪或刚刚就绪)。

对我来说还不清楚的是:在边缘模式下,我是否得知我不epoll_wait读书时发生的准备事件?尚未恢复的单发文件事件如何处理?

为了说明我为什么要问这个问题,请考虑以下情形:

  • 已连接10个非阻塞插座
  • 配置epoll_ctl为在边缘模式+ oneshot中准备好读取套接字时做出反应:EPOLLET | EPOLLONESHOT | EPOLLIN
  • epoll_wait 要发生的事情(最多报告10个事件)
  • linux唤醒我的进程并报告套接字#1和#2已准备好
  • read并处理数据套接字#1(直到E_AGAIN
  • read并处理数据套接字2(直到E_AGAIN
  • 在执行此操作时,套接字S接收数据
  • 我处理了所有事件,所以由于oneshot ,我以epoll_ctlin EPOLL_CTL_MOD模式重新触发了文件
  • 我的循环返回到epoll_wait下一批事件

好吧,那么是否epoll_wait 总是会通知套接字S已准备就绪?如果S为#1(即不重新设置),是否会发生事件?

linux epoll event-based-programming epollet

5
推荐指数
1
解决办法
1026
查看次数

一键*级别*触发的epoll():EPOLLONESHOT是否暗含EPOLLET?

是否可以epoll在单次触发水平模式下使用?
搜索时找不到任何信息;似乎每个人都使用边缘触发模式。

linux io epoll epollet

4
推荐指数
2
解决办法
924
查看次数

epoll:丢失一些 EPOLLOUT 事件?

这是我的服务器的样子:

-WorkerThread(s):

  • 调用 epoll_wait,接受连接,设置 fd 非阻塞(EPOLLIN | EPOLLOUT | EPOLLET | EPOLLRDHUP)
  • 在 EPOLLIN 事件上调用 recv 直到 EAGAIN 并将所有数据推送到全局 RecvBuffer(pthread_mutex synced)
  • 在 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 事件之间切换:

在接受:

event.events = …
Run Code Online (Sandbox Code Playgroud)

c c++ epoll asyncsocket epollet

3
推荐指数
1
解决办法
5538
查看次数

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

epoll联机帮助页说,如果没有读取,则EPOLLET注册的fd(边缘触发)不应通知两次EPOLLIN.
所以在EPOLLIN之后你需要清空缓冲区,然后epoll_wait才能在新数据上返回一个新的EPOLLIN.

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

30285 epoll_ctl(3, EPOLL_CTL_ADD, 9, {EPOLLIN|EPOLLPRI|EPOLLERR|EPOLLHUP|EPOLLET|0x2000, {u32=9, u64=9}}) = 0
30285 epoll_wait(3, {{EPOLLIN, {u32=9, u64=9}}}, 10, -1) = 1
30285 epoll_wait(3, {{EPOLLIN, {u32=9, u64=9}}}, 10, -1) = 1
30285 epoll_wait(3,  <unfinished ...>
30349 epoll_ctl(3, EPOLL_CTL_DEL, 9, NULL) = 0
30306 recv(9, "7u\0\0\10\345\241\312\t\20\f\32\r\10\27\20\2\30\200\10 \31(C0\17\32\r\10\27\20\2\30"..., 20000, 0) = 20000
30349 epoll_ctl(3, EPOLL_CTL_DEL, 9, NULL) = -1 ENOENT (No such file or directory)
30305 recv(9, " \31(C0\17\32\r\10\27\20\2\30\200\10 \31(C0\17\32\r\10\27\20\2\30\200\10 \31("..., 20000, 0) = 10011
Run Code Online (Sandbox Code Playgroud)

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

linux networking epoll epollet

2
推荐指数
1
解决办法
4372
查看次数

EPOLLET的用例是什么?

epoll在边缘触发模式下是一只奇怪的野兽。它要求该过程跟踪每个受监控FD的最后响应是什么。它要求流程能够无故障地处理所报告的每个事件(否则,我们可能会认为FD实际上没有被边缘触发行为所静音,而是没有报告任何东西)。

什么时候使用epoll这种方式有意义?

linux epoll epollet

1
推荐指数
1
解决办法
1683
查看次数