强制触发kevent
我在 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 调用返回?
I'm using kqueue for socket synchronization in OS X. I can register an event of interest like the following:
struct kevent change;
EV_SET(&change, connected_socket, EVFILT_READ, EV_ADD, 0, NULL, NULL);
kevent(k_queue_, &change, 1, NULL, 0, NULL);
And the question is, is there a way to trigger this event by force so that the waiting kevent call would return?
如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。
绑定邮箱获取回复消息
由于您还没有绑定你的真实邮箱,如果其他用户或者作者回复了您的评论,将不能在第一时间通知您!
发布评论
评论(3)
除了将数据自然写入套接字的另一端之外,还有一些可能性:)
shutdown(2)
该套接字的读取端 - 您将在中得到
(愚蠢),EV_EOF
>flags但我的问题是:你为什么需要这个?
编辑:
如果我正确理解您的评论,您正在寻找一种方法来解决写入事件的边沿触发行为(
EV_CLEAR
)。我认为正确的方法是当传出队列中没有任何内容时,从EVFILT_WRITE
取消注册您的套接字,然后再次重新注册当有数据要发送时。这需要更多的工作,但这就是它的工作原理,并且您不需要任何额外的系统调用,因为kevent(2)
接受更改和结果。查看libevent
并了解它如何处理此类东西。你使用的是非阻塞套接字,对吧?Some possibilities aside from natural writing of data to the other side of the socket :)
shutdown(2)
the read side of that socket - you'll getEV_EOF
inflags
(silly),My question though: why do you need this?
Edit:
If I understand your comments correctly you are looking for a way to get around edge-triggered behavior (
EV_CLEAR
) for write events. I believe that the proper way of doing this is to un-register your socket fromEVFILT_WRITE
when you don't have anything in the outgoing queue, then re-register it again when there's data to send. It's a bit more work, but that's how it works, and you don't need any additional system calls sincekevent(2)
accepts both changes and results. Take a look intolibevent
and see how it handles this sort of stuff. And you are using non-blocking sockets, right?我会推荐一个稍微不同的解决方案。
将另一个注册事件添加到 kqueue。具体来说是 EVFILT_USER。
您可以使用它来触发您想要唤醒 kevent() 线程的任何行为,而不会导致代码看起来很奇怪或难以维护。
中对其进行了真正的粗略测试
OSX 源代码在http://www.opensource.apple.com/source/xnu/xnu-1699.24.23/tools/tests/xnu_quick_test/kqueue_tests.c
I would recommend a slightly different solution.
Add another registered event to the kqueue. Specifically a EVFILT_USER.
You can use this to trigger whatever behavior you want to wake the kevent() thread up for without the code looking weird or being hard to maintain.
The OSX sources have a real rough test for it in
http://www.opensource.apple.com/source/xnu/xnu-1699.24.23/tools/tests/xnu_quick_test/kqueue_tests.c
OSX 10.6 和 FreeBSD 8.1 添加了对
EVFILT_USER
的支持,我们可以使用它从另一个线程唤醒事件循环。请注意,如果您使用它来实现自己的条件和 timedwait,您仍然需要锁以避免竞争条件,如 这个很好的答案。
有关完整代码示例,请参阅我的其他答案: https://stackoverflow.com/a/31174803/432
OSX 10.6 and FreeBSD 8.1 add support for
EVFILT_USER
, which we can use to wake up the event loop from another thread.Note that if you use this to implement your own condition and timedwait, you still need locks in order to avoid race conditions, as explained in this excellent answer.
See my other answer for a full code example: https://stackoverflow.com/a/31174803/432