- html - 出于某种原因,IE8 对我的 Sass 文件中继承的 html5 CSS 不友好?
- JMeter 在响应断言中使用 span 标签的问题
- html - 在 :hover and :active? 上具有不同效果的 CSS 动画
- html - 相对于居中的 html 内容固定的 CSS 重复背景?
我在边缘触发模式下使用 linux epoll。
每次有新连接传入时,我都会使用 EPOLLIN|EPOLLOUT|EPOLLET 标志将文件描述符添加到 epoll。我的第一个问题是:在 epoll_wait 返回后,检查每个就绪文件描述符发生哪种事件的正确方法是什么?我的意思是,我看到了一些示例代码,例如来自 https://github.com/yedf/handy/blob/master/raw-examples/epoll-et.cc第 124 行这样做:
for (int i = 0; i < n; i++) {
//...
if (events & (EPOLLIN | EPOLLERR)) {
if (fd == lfd) {
handleAccept(efd, fd);
} else {
handleRead(efd, fd);
}
} else if (events & EPOLLOUT) {
if (output_log)
printf("handling epollout\n");
handleWrite(efd, fd);
} else {
exit_if(1, "unknown event");
}
}
If more than one event occurs between epoll_wait(2) calls, are they combined or reported separately?
They will be combined.
if (revents & (EPOLLERR|EPOLLHUP)) {
//...
}
if ((revents & EPOLLIN) && rev->active) {
//....
rev->handler(rev);
}
if ((revents & EPOLLOUT) && wev->active) {
//....
wev->handler(wev);
}
On a somewhat related note: if you register for EPOLLIN and EPOLLOUT events and assuming you never fill up the send buffer, you still get the EPOLLOUT flag set in the event returned by epoll_wait each time EPOLLIN is triggered - see https://lkml.org/lkml/2011/11/17/234 for a more detailed explanation.
It's doesn't mean there's an EPOLLOUT "event", it just means a message is triggered (by the socket becoming readable) so you get a status update. In theory the program doesn't need to be told about EPOLLOUT here (it should be assuming the socket is writable already), but it doesn't do any harm.
最佳答案
多么棒的问题(因为我有几乎相同的问题)!我将总结一下我认为我现在所知道的内容,包括您的信息性问题/描述和有用的链接,希望更聪明的人能纠正任何错误。
是的,事件标志的 if/else 处理绝对是假的。可以肯定的是,至少两个 jar 头事件可以同时有效地到达。例如,自您上次调用 epoll_wait()
以来,读取端和写入端可能都已畅通无阻。 .当然,只要您 accept()
连接,读和写突然变得可能,所以你得到一个“事件”EPOLLIN|EPOLLOUT
.
我真的不明白 epoll_wait()
始终提供整个当前状态,而不仅仅是更改的状态部分 - 感谢您清除它。或许更清楚一点,epoll_wait()
除非在该套接字上发生更改,否则不会返回 fd,但如果确实发生了更改,它将返回代表当前状态的所有标志。所以,我发现自己盯着 EPOLLIN|EPOLLOUT
的流。事件想知道为什么它声称有一个“输出”事件,即使我还没有写任何东西。你的回答是正确的:它只是告诉我输出端仍然是可写的。
“我应该维护一面旗帜吗……” 是的,但我想,除了最微不足道的情况外,您可能最终会为您的读者/作者维持至少一点“我当前是否被阻止”状态.例如,如果您想以不同于数据到达方式的顺序处理数据(例如,将响应优先于请求以使您的服务器更能抵抗过载),您必须立即放弃仅让 I/到达的简单性。 O驱动一切。在写作的特殊情况下,epoll 根本没有足够的信息在“正确”的时间通知你。一旦你接受一个连接,就会有一个事件显示“你现在可以写”——但如果你是一个不可能已经收到来自客户端的请求的服务器,你可能没有什么可写的。 epoll 只是不知道你是否有东西要写,所以你总是不得不遭受本质上“无关”的事件,或者保持你自己的状态。
除了最简单的情况外,套接字文件描述符最终无法提供足够的信息来处理 I/O 事件,因此您总是必须将一些数据结构与它相关联,或者如果您愿意,也可以关联对象。所以,我的 C++ 看起来像:
nAwake = epoll_wait(epollFd, events, 100, milliseconds);
if(nAwake < 0)
{
perror("epoll_wait failed");
assert(false);
}
for(int iSocket=0; iSocket < nAwake; ++iSocket)
{
auto This = static_cast<Eventable*>(events[iSocket].data.ptr);
auto eventFlags = events[iSocket].events;
fprintf(stderr, "%s event on socket [%d] -> %s\n",
This->ClassName(), This->fd, DumpEvent(eventFlags));
This->Event(eventFlags);
}
在哪里
Eventable
是一个 C++ 类(或其派生类),它具有决定如何处理 epoll 传递的标志所需的所有状态。 (当然,这是让内核存储指向 C++ 对象的指针,需要一个非常清楚指针所有权/生命周期的设计。)
EPOLLRDHUP
.这个不高度便携的标志可以让你保存对
read()
的调用。 .如果客户端(curl 似乎很擅长引发这种行为)关闭连接的写入端(发送 FIN),您通常会发现当 epoll 告诉您
EPOLLIN
, 但是
read()
返回零字节。但是,Linux 会保留一个额外的位来指示客户端的写入端(您的读取端)已关闭。所以,如果你告诉 epoll 你想要
EPOLLRDHUP
事件您可以使用它来避免执行
read()
他们的唯一目的是告诉你作者关闭了他们的身边。
EPOLLIN
仍然会在
EPOLLRDHUP
时打开是,AFAIK。即使你做了
shutdown(fd, SHUT_RD)
.另一个例子是你通常会被驱使保持你自己对连接状态的想法。你更关心那些好心做半关机的客户
if you are implementing HTTP .
关于c++ - epoll_wait 即使带有 EPOLLET 标志也返回 EPOLLOUT,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/59288735/
在您的帮助和阅读其他资源后,我已经能够成功使用 epoll,我现在面临的问题是我需要发送到与 EPOLLOUT 事件返回不同的 FD,所以如果我有 5 个 FD,那么我需要发送到 1,然后发送到 4,
带有 EPOLLOUT 的 epoll TCP | EPOLLET只获取一次事件,即使我在获取第一个事件后发送数据也会超时。 而在UDP中,epoll在发送新数据后不断获取EPOLLOUT事件。 你能
写入器程序使用固定缓冲区的多次写入发送几 MB(几乎没有延迟)。处理程序在 EPOLLOUT | 中注册。 EPOLLET 标志。 MTU=16KB,写入缓冲区 = 4KB 或更多。 write(..
这是我的服务器的样子: -WorkerThread(s): 调用 epoll_wait,接受连接,设置 fd 非阻塞(EPOLLIN | EPOLLOUT | EPOLLET | EPOLLRDHUP
在监听套接字上,我设置了 EPOLLIN 位,但是在客户端连接上,我设置了 EPOLLIN | EPOLLOUT 位到 struct epoll_event 像这样: struct epoll_eve
我在边缘触发模式下使用 linux epoll。 每次有新连接传入时,我都会使用 EPOLLIN|EPOLLOUT|EPOLLET 标志将文件描述符添加到 epoll。我的第一个问题是:在 epoll
我有只读数据的 EPOLLIN 事件。不设置EPOLLOUT事件直接写数据可以吗? 最佳答案 当使用带级别触发通知的 epoll 时,除了套接字的输出缓冲区实际上是满的。这样做的影响是,即使您没有要发
关于事件是否合并的文档并不清楚,我的测试表明它们在某些情况下存在,但并非总是如此。 考虑 man 7 epoll: Since even with edge-triggered epoll, mult
假设我在使用 epoll_wait 添加要监视的描述符时指定了 EPOLLIN 和 EPOLLOUT 标志。从“epoll”联机帮助页中不清楚作为数组的一部分返回的每个 epoll_event 结构在
第一次 epoll() 用户。我正在使用 epoll 编写一个简单的 HTTP 客户端,以连接到我控制的主机上的 nginx Web 服务器。 这是我正在查看的事件序列 我关闭了(服务器)主机 我启动
我是一名优秀的程序员,十分优秀!