我试图理解kqueue中EV_DISABLE和EV_ENABLE的用例。
int KQueue = kqueue();
struct kevent ev = {
.ident = fd,
.filter = EVFILT_READ,
.flags = EV_ADD | EV_DISABLE,
.udata = somePtr
};
kevent(KQueue, &ev, 1, NULL, 0, NULL);
...
struct kevent ev = {
.ident = fd,
.filter = EVFILT_READ,
.flags = EV_ENABLE
};
kevent(KQueue, &ev, 1, &ev, 1, NULL);
现在,当最后一次致电kevent()
时,ev.udata
为NULL
而不是somePtr
。如果kevent()
指针更新了udata
指针,即使没有设置EV_ADD,也不是只启用该事件,那么允许您添加禁用事件的原因是什么?
答案 0 :(得分:1)
EV_ENABLE
的另一个用例与EV_DISPATCH
一起使用。在多线程场景中,您需要多个线程等待kevent()
调用中的事件。当一个事件发生时,没有EV_DISPATCH
,你的所有线程都会在同一个事件中被唤醒,导致一个雷鸣般的群体问题。使用EV_DISPATCH
,事件将传递到一个线程,并在此之后立即禁用(即,从用户空间的角度来看原子)。然后线程处理事件并可以重新启用它。
答案 1 :(得分:0)
kqueue
未更新udata
。您更新了udata
,将其保留为未初始化状态。您正在使用新值注册过滤器。 udata
的要点是与它交叉内核。您可以将自己的指针放在userland
。
禁用某个事件的重点是您希望它在另一个调用时返回,或者您不希望kqueue
在触发时返回,而是在其他时间返回。