я использую SetFileCompletionNotificationModes()
API для оптимизации циклов портов завершения ввода / вывода, но, похоже, он не работает должным образом.
Даже если я установлю FILE_SKIP_COMPLETION_PORT_ON_SUCCESS для сокетов и HANDLE, обратный вызов завершения порта ввода / вывода будет по-прежнему вызываться также, если ReadFile()
WriteFile()
WSARecv()
WSASend()
сделать возвращение synchronosly.
Я уверен, что 3 условия, которые MSDN говорит, должны быть истинными (порт завершения связан с дескриптором файла, файл открыт для асинхронного ввода-вывода, запрос сразу же возвращает успешный результат без возврата ERROR_PENDING), и все они выполнены. правда, так почему я до сих пор получаю вызовы завершения ввода / вывода?
Когда я звоню SetFileCompletionNotificationModes()
он возвращает успех, поэтому никаких ошибок или чего-либо еще, и система Windows 7.
Как я могу воспроизвести сценарий, когда после активации SetFileCompletionNotificationModes()
на моих сокетах / РУЧКАХ я ясно вижу, что обратный вызов завершения ввода-вывода не будет вызываться?
Я догадывался, что это происходит, когда я записываю несколько байтов в сокет, так как буфер сокета довольно большой, я не заполнил его, поэтому другая запись еще нескольких байтов не должна блокироваться, так как все еще остается много места в буфер, поэтому он должен немедленно вернуться, но не с ERROR_IO_PENDING, просто синхронно, верно? (более или менее аналогичным образом Unix EWOULDBLOCK / EAGAIN: когда я звоню write()
для нескольких байтов он возвращается немедленно и не возвращает EAGAIN, потому что в буфере записи еще есть место).
Ну, это не так. Даже для записи в сокет несколько раз нескольких байтов он все равно вызывает обратный вызов завершения ввода-вывода, что исключает преимущества настройки FILE_SKIP_COMPLETION_PORT_ON_SUCCESS
Я что-то упустил? Есть какие-нибудь подсказки по этому поводу?
ПРИМЕЧАНИЕ. Я знаю, что это не будет работать, если сокет совместим только с многоуровневыми поставщиками услуг (LSP), которые возвращают дескрипторы устанавливаемых файловых систем (IFS), но это не мой случай, он должен работать.
Кстати, я пытаюсь это также с трубами и файлами.
Не должны ли файлы никогда не вызывать обратные вызовы завершения ввода / вывода, потому что они никогда не блокируются, как в unix read()
а также write()
вызовы локальных файлов никогда не возвращают EWOULDBLOCK / EAGAIN, поэтому ReadFile()
а также WriteFile()
с дескриптором, установленным с FILE_SKIP_COMPLETION_PORT_ON_SUCCESS, должен немедленно вернуться?
Завершение сетевой записи генерируется только тогда, когда предоставленный вами буфер данных больше не требуется сетевым стеком. Трудно рассуждать о том, когда это произойдет, и это также не имеет никакого значения, и не о чем беспокоиться. Когда вы выпускаете перекрытую запись с FILE_SKIP_COMPLETION_PORT_ON_SUCCESS
set затем ваша операция записи вернет 0, если и только если завершение произошло синхронно. Напишите код для правильной обработки этого случая (это тот же код, который вам нужен для стороны recv) и забудьте об этом. Вы получите преимущества производительности и переключения контекста, когда это возможно, и ваш код будет работать правильно, когда это не так.
Что касается доступа к файловой системе, это зависит от драйверов файловой системы и, вероятно, от фактического оборудования. Увидеть Вот для получения некоторой информации о том, насколько сложно заставить какое-либо оборудование вообще выполнять асинхронную запись в файл. Затем обратите внимание, что когда я переключил тест, о котором я говорю, с рабочей станции с «обычными» дисками SATA на сервер с аппаратным рейдом, все было по-другому, и все записи всегда были полностью асинхронными …
Убедитесь, что вы подтвердите четвёртая состояние, указанное в документация:
Когда параметр FileHandle является сокетом, этот режим совместим только с многоуровневыми поставщиками услуг (LSP), которые возвращают дескрипторы устанавливаемых файловых систем (IFS). Чтобы определить, установлен ли LSP без IFS, используйте функцию WSAEnumProtocols и проверьте член dwServiceFlag1 в каждой возвращенной структуре WSAPROTOCOL_INFO. Если бит XP1_IFS_HANDLES (0x20000) очищен, то указанный LSP не является LSP IFS. Поставщикам, имеющим LSP не-IFS, рекомендуется перейти на платформу фильтрации Windows (WFP).
Также прочитайте этот билет поддержки MSDN: