Есть три важные функции при использовании kqueue.
int kqueue(void);
int kevent(int kq,
const struct kevent* changelist, int nchanges,
struct kevent *eventlist, int nevents,
const struct timespec *timeout);
EV_SET(kev, ident, filter, flags, fflags, data, udata);
Системный вызов
kqueue()
создает новую очередь событий ядра и возвращает дескриптор.Системный вызов
kevent()
используется для регистрации событий в очереди и возврата всех ожидающих событий пользователю.
- изменить kqueue
Когда вы хотите изменить очередь, например, удалить дескриптор файла сокета из kqueue или добавить сокет для прослушивания в kqueue, вы можете вызвать kevent()
, как показано ниже:
int kq = kqueue();
struct kevent event;
EV_SET(&event, listen_fd, EVFILT_READ, EV_ADD, 0, 0, NULL);
kevent(kq, &event, 1, NULL, 0, NULL);
Как показано выше, когда мы хотим изменить (удалить/добавить) событие в kqueue, есть два шага, первое, что мы должны сделать, это инициализировать kevent дескриптором файла, который мы хотим контролировать, второе — добавить этот kevent в kqueue с помощью kevent()
.
- мониторинг kqueue
Когда мы хотим мониторить kqueue, нам не нужно предоставлять changelist
и nchanges
параметры kevent()
. Нам просто нужно предоставить эти два параметра: eventlist
и nevents
, как показано ниже:
struct kevent event_list[MAX_EVENTS];
int num_events = kevent(kq, NULL, 0, event_list, MAX_EVENTS, NULL);
- удалить кевент
Когда клиент отключается, нам больше не нужен kevent, связанный с этим клиентом, поэтому нам нужно удалить этот kevent из kqueue. Но нам не нужно вызывать EV_SET()
и kevent()
, нам просто нужно закрыть этот файловый дескриптор. Потому что на странице руководства написано следующее:
Вызов close() для дескриптора файла удалит все kevents, которые ссылаются на этот дескриптор.
- исходный код
- ссылка
kqueue
Потоковый сервер, использующий Kqueue