1

我正在编写这个 FileDecriptor 类(继承自 tiabstract.FileDescriptor)来监听 /sys 中某个文件的事件。

不幸的是,它只能与 Epoll 的边缘触发模式一起使用。所以我目前正在使用一些 hackish 解决方案在添加后修改 epoll 列表中的文件描述符:

self.startReading()
self._reactor._poller._control(_epoll.CTL_MOD, self.fileno(), _epoll.IN|_epoll.ET)

有没有更好的方法来做到这一点?这会带来任何问题吗(例如,Twisted 是否有可能在某个时候再次移除 ET 标志)?

4

3 回答 3

1

It's quite possible that Twisted will remove this flag again. As you can see by the profusion of _s in your example, you're using tons of private APIs here, and they may all change without warning.

However, there's no public interface to do what you want. In my opinion, it is a kernel bug if an interface requires the use of a specific sycall interface to query its read/write readiness (like epoll) rather than following some general rule that works with epoll, select, poll, etc. My first inclination would be to file the bug against the linux kernel. However, if the kernel folks won't fix it, and you would like to contribute a patch with unit tests to expose a public interface for such linux+epoll-specific things to Twisted, please feel free to open a ticket.

于 2013-02-11T01:21:38.330 回答
1

需要注意的一件有趣的事情是 epoll 文件描述符本身是由 epoll 机制支持的。

如果你真的需要以特定的方式监控另一个描述符,而 epoll reactor 不支持,你可以创建自己的 epoll 文件描述符,随心所欲地配置它,然后询问 epoll(或 select,或 poll,甚至 gtk ) reactor 为您监控您的 epoll 文件描述符。当反应器说您的 epoll 文件描述符是可读的时,您可以对其执行零超时 epoll_wait 以了解它想告诉您的内容。

Twisted 已经完全支持这一点,您需要做的就是将IReadDescriptor接口实现为围绕您的 epoll 文件描述符的包装器。

于 2013-02-28T19:31:35.523 回答
0

8 年后,这仍然是 ET EPoll with twisted 搜索结果的顶部,所以这是我确定的解决方案。请注意,这是“标签外”,因为它是扭曲本身的扩展。如果您破坏了它,请不要纠缠扭曲的作者寻求帮助。首先是代码:

from twisted.internet.epollreactor import EPollReactor
from select import EPOLLET, EPOLLIN, EPOLLOUT

class EPETReactor(EPollReactor):
    epflags = EPOLLIN
    def addReader(self, reader):
        try:
            self._add(reader, self._reads, self._writes, self._selectables,
                      self.epflags, EPOLLOUT)
        except IOError as e:
            if e.errno == errno.EPERM:
                self._continuousPolling.addReader(reader)
            else:
                raise
    def startET(self):
        self.epflags = EPOLLIN | EPOLLET
    def stopET(self):
        self.epflags = EPOLLIN

请注意,这仍然涉及到twisted 的非公共API,但它允许您在一个地方这样做,无论您需要在哪里添加ET FD。如果 twisted 的内部变化足以破坏您的代码,您只需在此处修复它。此外,不会有任何事件未触发的边缘情况,因为事件在您添加 FD 和将其设置为 ET 模式之间到达。

另请注意,我们不只是一直强制 ET 模式,因此您可以切换到 ET 模式之前配置所需的任何 FD。

用例

如果您正在通过套接字读取MSG_PEEK并且只有一半的标头已到达,则选择是在套接字上忙于旋转和使用边缘触发模式(或从套接字读取并弄清楚如何将片段与文件一起发送) -descriptor 到其目的地,但这并不总是可能的)。

于 2021-02-09T09:21:54.693 回答