Какова цель kqueue EV_ENABLE и EV_DISABLE

#c #macos #kqueue

#c #macos #kqueue

Вопрос:

Я пытаюсь понять вариант использования EV_DISABLE и EV_ENABLE в kqueue.

 int KQueue = kqueue();

struct kevent ev = {
  .ident = fd,
  .filter = EVFILT_READ,
  .flags = EV_ADD | EV_DISABLE,
  .udata = somePtr
};

kevent(KQueue, amp;ev, 1, NULL, 0, NULL);

...

struct kevent ev = {
  .ident = fd,
  .filter = EVFILT_READ,
  .flags = EV_ENABLE
};

kevent(KQueue, amp;ev, 1, amp;ev, 1, NULL);
  

Теперь, когда последний вызов kevent() возвращает, ev.udata NULL вместо somePtr . Если kevent() обновляет udata указатель, даже если EV_ADD не установлен, вместо того, чтобы просто включить событие, в чем причина, по которой вам разрешено добавлять отключенное событие?

Ответ №1:

Другой вариант использования для EV_ENABLE — в сочетании с EV_DISPATCH . Это необходимо в многопоточном сценарии, где у вас есть несколько потоков, ожидающих событий в kevent() вызове. Когда происходит событие, без EV_DISPATCH которого все ваши потоки будут разбужены одним и тем же событием, вызывающим проблему с громоподобным стадом. При EV_DISPATCH этом событие доставляется в один поток и сразу после этого отключается (т. е. атомарно с точки зрения пользовательского пространства). Затем поток обрабатывает событие и может повторно включить его.

Ответ №2:

  1. kqueue не обновлялся udata . ВЫ обновили udata , оставив его неинициализированным. Вы регистрируете фильтр с новыми значениями. Смысл udata в том, чтобы пересечь ядро с ним. Вы можете сохранить свой собственный указатель userland .

  2. Смысл отключения события заключается в том, что вы хотите, чтобы оно возвращалось при другом вызове, или что вы не хотите, kqueue чтобы оно возвращалось при его запуске, но в другое время.