我在 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 调用返回?
除了将数据自然写入套接字的另一端之外的一些可能性:)
shutdown(2)
该套接字的读取端-您将进入EV_EOF
(flags
愚蠢),不过我的问题是:你为什么需要这个?
如果我正确理解您的评论,您正在寻找一种方法来解决EV_CLEAR
写入事件的边缘触发行为 ()。我相信这样做的正确方法是在传出队列中没有任何内容时取消注册套接字,然后在有数据要发送时再次重新注册。EVFILT_WRITE
它需要更多的工作,但这就是它的工作方式,并且您不需要任何额外的系统调用,因为它kevent(2)
接受更改和结果。看看libevent
它是如何处理这类事情的。而且您使用的是非阻塞套接字,对吗?
我会推荐一个稍微不同的解决方案。
将另一个注册事件添加到 kqueue。特别是 EVFILT_USER。
您可以使用它来触发您想要唤醒 kevent() 线程的任何行为,而不会使代码看起来很奇怪或难以维护。
OSX 来源对其进行了真正的粗略测试
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