Как осуществляется блокирование ввода-вывода без блокировки?

В Java или С# или некоторых других языках существуют неблокирующие объекты ввода-вывода, например, для сокетов.

Поэтому я могу передать свои функции обратного вызова неблокирующему IO, и как только неблокирующий IO получит что-либо, он вызовет мои обратные вызовы.

Мне интересно, как они реализованы. Если я создаю неблокирующий IO, за сценой, Java или С# просто создают фоновые потоки для них? или ОС, лежащая в основе, имеет встроенную поддержку для них?

Ответы

Ответ 1

В Windows есть базовая поддержка ОС для неблокирующих операций ввода-вывода, и Microsoft CLR использует это. Другие реализации CLR (mono), вероятно, тоже делают, но я точно не знаю. При выполнении асинхронных операций ввода-вывода в среде CLR Microsoft не существует корреляции между ожиданиями асинхронных операций ввода-вывода и потоками (или, по крайней мере, управляемыми потоками), ожидающими завершения этих операций ввода/вывода.

Подробнее о деталях на Win32-уровне см. http://msdn.microsoft.com/en-us/library/windows/desktop/aa365683(v=vs.85).aspx. Также информация о портах завершения ввода-вывода здесь: http://msdn.microsoft.com/en-us/library/aa365198(VS.85).aspx

Мое понимание таково:

  • Я запускаю операцию асинхронного ввода-вывода в потоке приложения.
  • Если он еще не создан, будет создана очередь (ну, действительно, конструкция уровня ядра, называемая портом завершения ввода-вывода, связанная с очередью в пространстве ядра моего приложения). В .NET-среде специально назначенный поток, называемый потоком портов завершения ввода-вывода, начнет ждать уведомлений о завершении ввода-вывода в этой очереди. Важно отметить, что я могу сделать любое количество запросов асинхронного ввода-вывода без увеличения количества портов завершения ввода-вывода.
  • ОС будет уведомлять приложение о завершении ввода-вывода, запустив сообщение о завершении ввода-вывода в очереди. Поток портов завершения ввода-вывода затем обработает это сообщение, вызвав обратный вызов завершения ввода-вывода в моем приложении .NET. Тем временем, если другие операции ввода/вывода завершатся, результаты будут занесены в очередь за текущими результатами обработки.

Предостережения выше:

  • Я уверен, что я принял участие в этом неправильно, но я считаю, что общий смысл этого верен. Эрик или кто-то может войти и исправить меня, где я ухожу.

  • В .NET существует несколько потоков портов завершения ввода-вывода. Я понятия не имею, как асинхронные запросы ввода-вывода распределяются между различными портами завершения ввода-вывода. Это может быть функция операционной системы (где I/O может возвращаться на любой порт, открытый приложением).

Для Java я уверен, что это зависит от реализации JVM и конкретной ОС. Я не знаю, что это достаточно хорошо, чтобы размышлять над этим.

EDIT: историческое обновление, гораздо больше здесь