问题标签 [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 - epoll - EPOLLET 容易出现竞争条件吗?
- 进程 B 在管道上进行 epoll (EPOLLIN|EPOLLET)。
- 进程 A 在管道中写入 1KiB。
- 进程 B 唤醒。
- 进程 B 从管道中读取 1KiB。
- 进程 A 在管道中写入 1KiB。
- 进程 B 在管道上进行 epoll。
管道的状态在 epoll 期间没有改变,但自上次读取后发生了变化。进程B会再次唤醒吗?
linux - 多线程 epoll 服务器:唤醒睡在同一个 epoll fd 上的 N 个线程
我有一个多线程的 epoll 服务器。我创建了一个 epoll fd,然后我将有 X 个线程休眠,等待来自SAME epoll fd的epoll_wait()
任何事件。
现在我的问题是:如何唤醒 N 个线程,N > 1 && N < X?
到目前为止,我一直在使用 Linux 特定的 eventfd 工具,它只使用 1 个线程就可以很好地工作,但是现在有多个线程等待SAME epoll fd,出现了一个问题:
案例 1) LT:如果我使用“级别触发”模式添加我的 eventfd,当我写入 eventfd 时,所有线程都会唤醒,这就是级别触发模式的工作方式:一旦 fd 更改状态,让我们唤醒所有线程。
N = X
案例 2) ET:如果我使用“边缘触发”模式添加我的 eventfd,当我写入 eventfd 时只有 1 个线程会唤醒,这就是边缘触发模式的工作原理:在我收到EAGAIN
来自read(eventfd, ...);
.
N = 1
案例3)我也尝试过使用自管道技巧,向管道写入N次会唤醒N个线程。相反,它不起作用:它不可靠,有时一个线程从管道中读取 2 个“令牌”,有时是 1 或 3 个。
N = 随机
在我尝试过的所有情况下,我不能只得到 N=N,我不能只唤醒 N 个线程,而是 1 或 ALL,或 RANDOM。我错过了什么?有什么想法吗?注意:我也尝试了 eventfd 特定的EFD_SEMAPHORE
标志,没有任何帮助。
event-handling - 为 epoll 线程重新配置文件描述符是否安全?
从这个问题我知道我可以epoll_ctl(2)
在另一个线程阻塞时调用epoll_wait(2)
。不过我还有一个问题。
当epoll
与EPOLLONESHOT
标志一起使用时,只会触发一个事件,并且 fd 必须使用epoll_ctl(2)
. 这是必要的,因此只有一个线程将从 fd 中读取并适当地处理结果。
以下是在某种程度上可视化我假设的问题的时间线:
当 fd 在接收到一个块后重新配置时,问号上会发生什么?会epoll
触发一个EPOLLIN
事件,还是会无限期地阻塞,尽管套接字是可读的?我的架构完全合理吗?
linux - 非 epoll_waiting 时是否正在监视 epoll 事件
我对基于事件的编程相当陌生。我正在尝试使用epoll
's edge-mode,它显然只表示已经准备好读/写的文件(而不是表示所有准备好的文件的 level-mode ,无论是否已经准备好或刚刚准备好)。
我不清楚的是:在边缘模式下,我是否知道在我不在时发生的准备事件epoll_wait
?尚未重新武装的一次性文件上的事件呢?
为了说明我问这个问题的原因,请考虑以下场景:
- 连接了 10 个非阻塞套接字
- 配置
epoll_ctl
为在套接字准备好读取时做出反应,在edge-mode + oneshot中:EPOLLET | EPOLLONESHOT | EPOLLIN
epoll_wait
发生某事(最多报告 10 个事件)- linux 唤醒我的进程并报告套接字 #1 和 #2 已准备好
- 我
read
和处理数据套接字#1(直到E_AGAIN
) - 我
read
和处理数据套接字#2(直到E_AGAIN
) - 当我这样做时,套接字S接收数据
epoll_ctl
我处理了所有事件,所以我用in模式重新武装触发的文件EPOLL_CTL_MOD
,因为 oneshot- 我的循环回到
epoll_wait
ing 下一批事件
好的,那么最后一个epoll_wait
总是会被通知套接字S的准备情况吗?如果S是 #1 的事件(即它没有重新武装)?
multithreading - C 中带有 epoll 和 EPOLLET 的多线程 TCP 侦听器
我想使用 epoll 和EPOLLET
.
我已经看到有几种可能性:
每个线程都有自己的 epoll fd,
bind()
使用SO_REUSEPORT
(但仅限于 Linux 内核 3.9)并处理自己的连接。EPOLLONESHOT
在这种情况下不需要,因为每个线程都处理自己的文件描述符。有一个接受连接的主线程和几个处理这些连接的工作线程。每个工作线程都有自己的 epoll fd。在这种情况下,主线程如何在工作线程之间公平分配连接?它可以使用循环方式将文件描述符添加到另一个线程的 epoll fd(但可能会发生该特定线程仍在忙于处理另一个连接)。或者可以将连接添加到全局队列中,并且主线程将使用
pthread_cond_signal()
,但是我们需要一个互斥锁和一个条件变量。有一个接受连接的主线程和几个处理这些连接的工作线程。在这种情况下将需要一个全局 epoll fd,
EPOLLONESHOT
因此并非所有线程都为同一事件唤醒。
我知道,如果EPOLLET
使用,一旦我收到有关事件的通知,我必须耗尽 fd,直到我得到EAGAIN
.
如果不支持套接字选项SO_REUSEPORT
(旧内核),哪个选项最好?
c - 为什么 EPOLLOUT 会改变 EPOLLIN 的处理方式?
文档不清楚事件是否合并,我的测试表明它们在某些情况下但并非总是如此。
考虑man 7 epoll
:
由于即使使用边缘触发的 epoll,在接收到多个数据块时也可以生成多个事件, 调用者可以选择指定 EPOLLONESHOT 标志...
和问答部分:
Q7 如果 epoll_wait(2) 调用之间发生了多个事件,是合并还是单独报告?
A7 它们将被合并。
我假设手册中的第一条语句意味着在从套接字读取、数据包到达、您读取它、然后另一个数据包到达等情况下,您可以接收多个 EPOLLIN 事件。Q&A 部分的答案是讨论不同的事件,如 EPOLLIN 和 EPOLLOUT。如果我错了,请纠正我。
我正在玩一些代码,以便更好地理解 epoll 是如何工作的,并且对于基于是否设置了另一个事件,它似乎对同一种事件的行为有所不同。更准确地说,如果我只等待 EPOLLIN,则多个输入会生成一个事件,但如果我同时等待 EPOLLIN 和 EPOLLOUT,则多个输入会生成多个事件。
这是我用来测试的代码:
按回车后的输出显示 EPOLLIN 和 EPOLLOUT 都收到了,此消息出现的次数与按回车的次数一样多,然后显示只有 EPOLLOUT 正在生成。
但是如果你编译没有EPOLLOUT标志的程序并多次按下return,单个事件将只报告一次。
如果我删除read
呼叫,则在设置 EPOLLOUT 时继续报告 EPOLLIN,但在仅设置 EPOLLIN 时不会报告。
行为取决于它正在等待的事件还是我的测试代码有问题?如果它是依赖的,我可以放心它将来不会改变吗?
linux - One-shot *level*-triggered epoll():EPOLLONESHOT 是否暗示 EPOLLET?
是否可以epoll
在单次触发模式下使用?
我搜索时找不到任何有关它的信息;似乎每个人都使用边缘触发模式。
linux - Socket epoll:EPOLL_CTL_MOD 会重置边沿触发吗?
首先将套接字添加到 epoll 集以进行边缘触发读取:
现在等待数据:
假设,假设有 20+ 字节的数据可用。但随后的代码希望以 10 字节块的形式从流中解析消息:
所以此时,您可能会说,“如果他调用epoll_wait
,他的代码可能会挂起或超时,即使套接字流中还有 10 个字节尚未读取。” 你是对的。
但是我的代码并没有返回到 epoll_wait,而是实际上切换了 epoll 标志,以便它可以在同一个套接字上发送回响应。
请注意,不再设置 EPOLLIN。然后代码执行标准循环,send
直到epoll_wait
发送完整的响应。
设置消息响应后,代码将返回以边沿触发模式读取:
接着是等待:
现在假设自上次从套接字读取后没有额外的数据到达,由于边缘级别没有改变sock
,上述挂起(或超时)吗?epoll_wait
或者 EPOLLIN 被关闭再打开的事实是否允许重置边缘状态,以便上述epoll_wait
调用将立即返回以指示套接字上可用的数据?
linux - EPOLLET 的用例是什么?
epoll
在边沿触发模式下是一头奇怪的野兽。它要求该过程跟踪每个受监视 FD 的最后响应是什么。它要求进程无误地处理每个报告的事件(否则我们可能会认为 FD 没有报告任何内容,而实际上它被边缘触发行为静音)。
epoll
边缘触发有意义的用例有哪些?
python - 阻止从 Python 读取 GPIO:如何使用 epoll() 和 select.EPOLLET 进行阻止
我正在嵌入式系统(ARM 内核)上尝试从 Python 进行 GPIO 访问,该系统正在运行使用 Buildroot(内核 4.1.15)构建的 linux。
我希望我的代码阻塞等待 GPIO2 上的引脚更改(即我不想通过重复调用“读取”来轮询引脚)。我正在尝试在边缘触发模式下使用“epoll”来做到这一点:
请参阅Python 文档以了解 epoll。select.EPOLLET标志用于获取 epoll 的边沿触发。另请参阅epoll 的 Linux 文档。
为简单起见,我已经使用 sysfs 从控制台设置了 GPIO 引脚:
这是我的 Python 代码:
为了进行测试,我从信号发生器以每周期约 2 秒的速度向输入引脚馈送方波,因此我可以看到引脚何时发生变化。
当我在嵌入式系统上运行它时,我得到了这个:
代码在 1 秒休眠时休眠,然后在下一次迭代中,poll() 立即返回并且不会阻塞。它应该阻塞,因为我的输入仅在每 2 秒一个上升沿运行。
为什么“poll()”没有阻塞?
==== 编辑:====
最初,当我尝试使用“select.EPOLLET”时,代码导致了一个奇怪的错误:
但是,我发现我不小心使用了 myPoll = select.poll()而不是epoll()。代码现已修复。