используя kqueue для EVFILT_USER

Мне трудно понять, как использовать kqueue для событий пользовательского пространства.
Я ищу 2 варианта использования.
Вариант использования 1: событие ручного сброса
Вариант использования 2: событие автоматического сброса

Я думаю, что понимаю, как использовать kqueue() и kevent(), но я не совсем понимаю, как события, переданные в kevent(), ищут связанные операции:
Пусть будет переменная struct kevent с именем "event".
Предположим, у нас нет проблем с поиском нового идентификатора события, который не конфликтует с другими идентификаторами событий для этого экземпляра kqueue с именем "eventId".

  1. Создать пользовательское событие: EV_SET(&event, eventId, EVFILT_USER, EV_ADD, NOTE_FFNOP, 0, NULL)
  2. Уничтожить пользовательское событие: EV_SET(&event, eventId, EVFILT_USER, EV_DESTROY, NOTE_FFNOP, 0, NULL)
  3. Установите пользовательское событие: EV_SET(&event, eventId, EVFILT_USER, ?????, NOTE_FFNOP, 0, NULL)
  4. Сбросить пользовательское событие: EV_SET(&event, eventId, EVFILT_USER, ??EV_CLEAR???, NOTE_FFNOP, 0, NULL )
  5. Импульсное пользовательское событие: EV_SET(&event, eventId, EVFILT_USER, 0, NOTE_TRIGGER, 0, NULL )
  6. Я думаю, что в цикле ожидания будет вырезано: if( event.filter == EVFILT_USER && event.ident == eventId ) { // это мое событие! Сделай что-нибудь! }

Смотрите ???? в приведенных выше вызовах EV_SET(), чтобы увидеть, где мне нужна помощь.
Для варианта использования 1 (событие ручного сброса) операция (1) Create может выглядеть иначе, чем вариант использования 2 (событие автоматического сброса).
Операции (3) и (4) Я полностью в темноте. Могу ли я нуждаться в EV_ENABLE/EV_DISABLE для них? Где вписывается EV_CLEAR?
Пока я предполагаю, что мне не нужно делать ничего в операции (6), кроме "диспетчеризации". Я совершенно уверен, что операция (5) может работать так, как я описал выше.

Я провел большую часть дня, пытаясь найти документацию или образцы, показывающие, как это делается. Я нашел в кодовой базе Apple тестовую программу kqueue, но я сомневаюсь, что она делает это правильно. Кроме того, он отправляет только 1 событие в тесте, и это событие завершает цикл принимающего потока. Так что это не помогает мне понять детали для моих двух вариантов использования.

Я планирую использовать его под FreeBsd 9.1 на машине x86... пока.


person BitTickler    schedule 18.04.2013    source источник


Ответы (1)


После некоторых экспериментов я обнаружил:

  1. Создать пользовательское событие: EV_SET(&ev, идентификатор, EVFILT_USER, EV_ADD, NOTE_FFCOPY, 0, NULL )
  2. Уничтожить пользовательское событие: EV_SET(&ev, идентификатор, EVFILT_USER, EV_DELETE, 0, 0, 0)
  3. Установить пользовательское событие: EV_SET(&event, m_eventId, EVFILT_USER, EV_ENABLE, NOTE_FFCOPY|NOTE_TRIGGER|0x1, 0, NULL)
  4. Сбросить пользовательское событие: EV_SET(&event, m_eventId, EVFILT_USER, EV_DISABLE, EV_CLEAR|NOTE_FFCOPY, 0, NULL)
  5. Пользовательское событие Pulse: не тестировалось... пока использовал вариант 1.
  6. Фрагмент кода ожидания: как указано в исходном сообщении.

Тест работает как шарм. В моем тесте я сделал NOTE_FFCOPY, но я не думаю, что это необходимо.

Пользовательские события имеют 2 состояния - сигнализируются, не сигнализируются. Кажется, что EV_ENABLE и EV_DISABLE устанавливают эти состояния.

Тест подтвердил, что о событиях в сигнальном состоянии фактически сообщает kevent() неоднократно.

person user2173833    schedule 18.04.2013
comment
Помогли мне понять пользовательские события, спасибо! Также обратите внимание, что NOTE_TRIGGER в сочетании с EV_ONESHOT может быть полезно для разблокировки вызова kevent(). - person samvv; 29.07.2019