SetFileCompletionNotificationModes, кажется, не работает должным образом

я использую 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, должен немедленно вернуться?

1

Решение

Завершение сетевой записи генерируется только тогда, когда предоставленный вами буфер данных больше не требуется сетевым стеком. Трудно рассуждать о том, когда это произойдет, и это также не имеет никакого значения, и не о чем беспокоиться. Когда вы выпускаете перекрытую запись с FILE_SKIP_COMPLETION_PORT_ON_SUCCESS set затем ваша операция записи вернет 0, если и только если завершение произошло синхронно. Напишите код для правильной обработки этого случая (это тот же код, который вам нужен для стороны recv) и забудьте об этом. Вы получите преимущества производительности и переключения контекста, когда это возможно, и ваш код будет работать правильно, когда это не так.

Что касается доступа к файловой системе, это зависит от драйверов файловой системы и, вероятно, от фактического оборудования. Увидеть Вот для получения некоторой информации о том, насколько сложно заставить какое-либо оборудование вообще выполнять асинхронную запись в файл. Затем обратите внимание, что когда я переключил тест, о котором я говорю, с рабочей станции с «обычными» дисками SATA на сервер с аппаратным рейдом, все было по-другому, и все записи всегда были полностью асинхронными …

2

Другие решения

Убедитесь, что вы подтвердите четвёртая состояние, указанное в документация:

Когда параметр FileHandle является сокетом, этот режим совместим только с многоуровневыми поставщиками услуг (LSP), которые возвращают дескрипторы устанавливаемых файловых систем (IFS). Чтобы определить, установлен ли LSP без IFS, используйте функцию WSAEnumProtocols и проверьте член dwServiceFlag1 в каждой возвращенной структуре WSAPROTOCOL_INFO. Если бит XP1_IFS_HANDLES (0x20000) очищен, то указанный LSP не является LSP IFS. Поставщикам, имеющим LSP не-IFS, рекомендуется перейти на платформу фильтрации Windows (WFP).

Также прочитайте этот билет поддержки MSDN:

API SetFileCompletionNotificationModes заставляет порт завершения ввода / вывода работать неправильно, если установлен LSP без IFS

1

По вопросам рекламы [email protected]