Какой эквивалент epoll/kqueue/select лучше всего подходит для Windows?
-
09-06-2019 - |
Вопрос
Какое средство уведомления о событиях ввода-вывода в Windows является лучшим?
Под лучшим я имею в виду то, что...
- не имеет ограничения на количество дескрипторов входных файлов
- работает со всеми файловыми дескрипторами (файлы диска, сокеты,...)
- обеспечивает различные режимы уведомлений (по фронту, по пределу)
Решение
В Windows асинхронные операции выполняются с помощью файловых операций, а не дескрипторов.Существует несколько способов дождаться асинхронного завершения файловых операций.
Например, если вы хотите узнать, когда данные доступны в сетевом сокете, выполните запрос асинхронного чтения в сокете, и когда он завершится, данные будут доступны и получены.
В Win32 асинхронные операции используют OVERLAPPED
структура, содержащая состояние о невыполненной операции ввода-вывода.
- Свяжите файлы с Порт завершения ввода-вывода и отправлять асинхронные запросы ввода-вывода.Когда операция завершается, она помещает сообщение о завершении в очередь, которую ваши рабочие потоки могут ожидать и получать по мере их прибытия.Вы также можете помещать в очередь определенные пользователем сообщения.Нет ограничений на количество файлов или сообщений в очереди, которые можно использовать с портом завершения.
- Отправляйте каждую операцию ввода-вывода с событием.Событие, связанное с операцией, станет сигнализированным (удовлетворит ожидание) после ее завершения.Использовать
WaitForMultipleObjects
ждать всех событий одновременно.Это имеет тот недостаток, что можно только ждатьMAXIMUM_WAIT_OBJECTS
предметы сразу (64).Вы также можете одновременно ожидать других типов событий (завершение процесса/потока, мьютексы, события, семафоры). - Использовать пул потоков.Пул потоков может принимать неограниченное количество объектов и файловых операций для ожидания и выполнения определяемая пользователем функция по завершении каждого.
- Использовать
ReadFileEx
иWriteFileEx
стоять в очереди Асинхронные вызовы процедур (APC) к вызывающему потоку иSleepEx
(илиWaitFor{Single|Multiple}ObjectsEx
) сAlertable TRUE
для получения уведомления о каждой операции после ее завершения.Этот метод аналогичен порту завершения ввода-вывода, но работает только для одного потока.
Ядро Windows NT не делает различий между сокетом, дисковым файлом, каналом и т. д.файловые операции внутри:все эти параметры будут работать со всеми типами файлов.
Другие советы
Либув
libuv
предлагает событийный ввод-вывод для Unix и Windows и поддерживает сокеты, файлы и каналы.Это уровень платформы Node.js.
Более подробная информация находится по адресу: http://nikhilm.github.io/uvbook/introduction.html
Насколько мне известно, его пока нет.Мы с другом работаем над реализацией epoll для Windows с открытым исходным кодом (ссылка ниже), но у нас возникают проблемы с выяснением того, как заставить ее действовать так же, как реализация для Linux.
Текущие препятствия:
- В Linux дескрипторы файлов и дескрипторы сокетов взаимозаменяемы, а в Windows — нет.Оба должны быть совместимы с реализацией epoll.
- В Windows довольно сложно получить события ядра...именно так работает epoll в Linux.Мы предполагаем, что программа, использующая нашу кроссплатформенную библиотеку epoll, будет работать в Windows заметно медленнее, чем в Linux.
Я постараюсь вернуться и обновить этот пост по мере продвижения проекта.
Функция select() является POSIX и может использоваться в Windows, включая «winsock.h» или «winsock2.h».