2

我试图了解 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.udataNULL而不是somePtr. 如果即使未设置 EV_ADD 也kevent()更新指针,而不是仅启用事件,那么允许您添加禁用事件的原因是什么?udata

4

2 回答 2

1

的另一个用例EV_ENABLE是与EV_DISPATCH. 这在多线程场景中是必要的,您有多个线程等待kevent()调用中的事件。当事件发生时,如果没有EV_DISPATCH,您的所有线程都将在同一事件上被唤醒,从而导致雷鸣般的羊群问题。使用EV_DISPATCH,事件被传递到一个线程并在此之后立即禁用(即从用户空间的角度来看是原子的)。然后线程处理该事件并可能重新启用它。

于 2017-10-05T09:15:53.073 回答
0
  1. kqueue没有更新udata。您udata通过保持未初始化来更新。您正在使用新值注册过滤器。的重点udata是与它交叉内核。您可以将自己的指针保留在userland.

  2. 禁用事件的重点是您希望它在另一个调用中返回,或者您不想kqueue在触发它时导致返回,而是在不同的时间返回。

于 2017-07-11T08:51:14.020 回答