用武力触发kevent

时间:2010-07-28 15:50:34

标签: macos sockets freebsd kqueue

我在OS X中使用kqueue进行套接字同步。我可以注册一个感兴趣的事件,如下所示:

struct kevent change;
EV_SET(&change, connected_socket, EVFILT_READ, EV_ADD, 0, NULL, NULL);
kevent(k_queue_, &change, 1, NULL, 0, NULL);

问题是,是否有办法强制触发此事件,以便等待kevent调用返回?

3 个答案:

答案 0 :(得分:2)

除了将数据自然写入套接字的另一端之外的一些可能性:)

  • shutdown(2)该套接字的读取方 - 您将在EV_EOF中获得flags(愚蠢),
  • 使用timeout参数并调用相同的处理函数
  • 当您需要中断等待时使用self-pipe trick

我的问题是:你为什么需要这个?

编辑:

如果我正确理解您的评论,那么您正在寻找一种方法来解决写入事件的边缘触发行为(EV_CLEAR)。我相信这样做的正确方法是在传出队列中没有任何内容时从EVFILT_WRITE 取消注册套接字,然后在有数据时再次重新注册它发送。这是一个更多的工作,但它是如何工作的,你不需要任何额外的系统调用,因为kevent(2)接受更改和结果。看看libevent,看看它是如何处理这类东西的。你正在使用非阻塞套接字,对吧?

答案 1 :(得分:1)

我会建议稍微不同的解决方案。

将另一个注册事件添加到kqueue。特别是EVFILT_USER。

你可以使用它来触发你想要唤醒kevent()线程的任何行为,而代码看起来很奇怪或难以维护。

OSX来源在

中进行了真正粗略的测试

http://www.opensource.apple.com/source/xnu/xnu-1699.24.23/tools/tests/xnu_quick_test/kqueue_tests.c

答案 2 :(得分:1)

OSX 10.6和FreeBSD 8.1添加了对EVFILT_USER的支持,我们可以用它来唤醒另一个线程的事件循环。

请注意,如果你使用它来实现自己的条件和timedwait,你仍然需要锁定以避免竞争条件,如this excellent answer中所述。

有关完整的代码示例,请参阅我的其他答案:https://stackoverflow.com/a/31174803/432