На нашем сайте мы используем cookie для сбора информации технического характера и обрабатываем IP-адрес вашего местоположения. Продолжая использовать этот сайт, вы даете согласие на использование файлов cookies. Здесь вы можете узнать, как мы пользуемся файлами cookies.
Я согласен
логотип upread.ru

Синхронный и асинхронный ввод-вывод Windows


Существует два типа синхронизации ввода-вывода: синхронный ввод-вывод и асинхронный ввод-вывод. Асинхронный ввод-вывод также называется перекрывающимся вводом-выводом.

При синхронном файловом вводе-выводе поток запускает операцию ввода-вывода и немедленно переходит в состояние ожидания до завершения запроса ввода-вывода. Поток, выполняющий асинхронный файловый ввод-вывод, отправляет запрос ввода-вывода ядру, вызывая соответствующую функцию. Если запрос принят ядром, вызывающий поток продолжает обработку другого задания до тех пор, пока ядро не подаст потоку сигнал о завершении операции ввода-вывода. Затем он прерывает свою текущую работу и обрабатывает данные из операции ввода-вывода по мере необходимости.

Эти два типа синхронизации показаны на следующем рисунке.

синхронный и асинхронный ввод-вывод

В ситуациях, когда запрос ввода-вывода, Как ожидается, займет много времени, таких как обновление или резервное копирование большой базы данных или медленный канал связи, асинхронный ввод-вывод, как правило, является хорошим способом оптимизации эффективности обработки. Однако для относительно быстрых операций ввода-вывода накладные расходы на обработку запросов ввода-вывода ядра и сигналов ядра могут сделать асинхронный ввод-вывод менее выгодным, особенно если требуется выполнить много быстрых операций ввода-вывода. В этом случае синхронный ввод-вывод был бы лучше. Механизмы и детали реализации выполнения этих задач варьируются в зависимости от типа используемого дескриптора устройства и конкретных потребностей приложения. Другими словами, обычно существует несколько способов решения проблемы.

Соображения по поводу синхронного и асинхронного ввода-вывода

Если файл или устройство открыты для синхронного ввода-вывода (то есть FILE_FLAG_OVERLAPPED не указан), последующие вызовы функций, таких как WriteFile, могут блокировать выполнение вызывающего потока до тех пор, пока не произойдет одно из следующих событий:

  • Операция ввода-вывода завершается (в данном примере это запись данных).
  • Возникает ошибка ввода-вывода. (Например, другой конец закрыт)
  • В самом вызове была допущена ошибка (например, один или несколько параметров недопустимы).
  • Другой поток в процессе вызывает функцию CancelSynchronousIo, используя дескриптор потока заблокированного потока, который завершает ввод-вывод для этого потока, не выполнив операцию ввода-вывода.
  • Заблокированный поток завершается системой; например, завершается сам процесс или другой поток вызывает функцию TerminateThread, используя дескриптор заблокированного потока. (Это обычно считается последним средством и не очень хорошим дизайном приложения.)
В некоторых случаях эта задержка может быть неприемлемой для дизайна и назначения приложения, поэтому разработчики приложений должны рассмотреть возможность использования асинхронного ввода-вывода с соответствующими объектами синхронизации потоков, такими как порты завершения ввода-вывода.

Процесс открывает файл для асинхронного ввода-вывода при вызове CreateFile, указав флаг FILE_FLAG_OVERLAPPED в параметре dwFlagsAndAttributes. Если FILE_FLAG_OVERLAPPED не указан, файл открывается для синхронного ввода-вывода. Когда файл открыт для асинхронного ввода-вывода, указатель на перекрывающуюся структуру передается в вызов ReadFile и WriteFile. При выполнении синхронного ввода-вывода эта структура не требуется в вызовах ReadFile и WriteFile.

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

Хотя CreateFile является наиболее распространенной функцией, используемой для открытия файлов, дисковых томов, анонимных каналов и других подобных устройств, операции ввода-вывода также могут выполняться с использованием типа дескриптора из других системных объектов, таких как сокет, созданный функциями socket или accept.

Дескрипторы объектов каталога получаются путем вызова функции CreateFile с атрибутом FILE_FLAG_BACKUP_SEMANTICS. Дескрипторы каталогов почти никогда не используются—приложения резервного копирования являются одним из немногих приложений, которые обычно используют их.

После открытия объекта file для асинхронного ввода-вывода перекрывающаяся структура должна быть правильно создана, инициализирована и передана в каждый вызов таких функций, как ReadFile и WriteFile. При использовании ПЕРЕКРЫВАЮЩЕЙСЯ структуры в асинхронных операциях чтения и записи имейте в виду следующее:

  • Не освобождайте и не изменяйте перекрывающуюся структуру или буфер данных до тех пор, пока не будут завершены все асинхронные операции ввода-вывода с файловым объектом.
  • Если вы объявите указатель на перекрывающуюся структуру как локальную переменную, не выходите из локальной функции до тех пор, пока не будут завершены все асинхронные операции ввода-вывода с файловым объектом. Если локальная функция будет выведена преждевременно, перекрывающаяся структура выйдет за пределы области видимости и будет недоступна для любых функций ReadFile или WriteFile, с которыми она сталкивается за пределами этой функции.
Вы также можете создать событие и поместить дескриптор в перекрывающуюся структуру; затем функции ожидания можно использовать для ожидания завершения операции ввода-вывода, ожидая дескриптора события.

Как уже говорилось ранее, при работе с асинхронным дескриптором приложения должны проявлять осторожность при определении времени освобождения ресурсов, связанных с указанной операцией ввода-вывода на этом дескрипторе. Если дескриптор освобожден преждевременно, ReadFile или WriteFile могут неправильно сообщить о завершении операции ввода-вывода. Кроме того, функция WriteFile иногда возвращает TRUE со значением GetLastError ERROR_SUCCESS, даже если она использует асинхронный дескриптор (который также может возвращать FALSE с ERROR_IO_PENDING).

Программисты, привыкшие к синхронному проектированию ввода-вывода, обычно освобождают ресурсы буфера данных в этот момент, потому что TRUE и ERROR_SUCCESS означают, что операция завершена. Однако, если порты завершения ввода-вывода используются с этим асинхронным дескриптором, пакет завершения также будет отправлен, даже если операция ввода-вывода завершится немедленно. Другими словами, если приложение освобождает ресурсы после того, как WriteFile возвращает TRUE с ERROR_SUCCESS в дополнение к процедуре завершения порта ввода-вывода, оно будет иметь условие двойной свободной ошибки. В этом примере рекомендация будет заключаться в том, чтобы позволить процедуре порта завершения нести исключительную ответственность за все операции по освобождению таких ресурсов.

Система не поддерживает указатель файла на асинхронных дескрипторах файлов и устройств, поддерживающих указатели файлов (то есть устройств поиска), поэтому положение файла должно быть передано функциям чтения и записи в соответствующих элементах данных смещения перекрывающейся структуры.

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

Приложение также может дождаться дескриптора файла для синхронизации завершения операции ввода-вывода, но это требует крайней осторожности. Каждый раз при запуске операции ввода-вывода операционная система устанавливает дескриптор файла в состояние без сигнала. Каждый раз, когда операция ввода-вывода завершена, операционная система устанавливает дескриптор файла в сигнальное состояние.

Поэтому, если приложение запускает две операции ввода-вывода и ожидает дескриптор файла, нет никакого способа определить, какая операция завершена, когда дескриптор установлен в сигнальное состояние. Если приложение должно выполнить несколько асинхронных операций ввода-вывода в одном файле, оно должно ожидать дескриптора события в определенной ПЕРЕКРЫВАЮЩЕЙСЯ структуре для каждой операции ввода-вывода, а не общего дескриптора файла.

Чтобы отменить все отложенные асинхронные операции ввода-вывода, используйте либо:

  • CancelIo—эта функция отменяет только операции, выполняемые вызывающим потоком для указанного дескриптора файла.
  • CancelIoEx—эта функция отменяет все операции, выполняемые потоками для указанного дескриптора файла.
Используйте CancelSynchronousIo для отмены отложенных синхронных операций ввода-вывода.

Функции ReadFileEx и WriteFileEx позволяют приложению указать процедуру для выполнения (FileIOCompletionRoutine) после завершения асинхронного запроса ввода-вывода.



Автор этого материала - я - Пахолков Юрий. Я оказываю услуги по написанию программ на языках Java, C++, C# (а также консультирую по ним) и созданию сайтов. Работаю с сайтами на CMS OpenCart, WordPress, ModX и самописными. Кроме этого, работаю напрямую с JavaScript, PHP, CSS, HTML - то есть могу доработать ваш сайт или помочь с веб-программированием. Пишите сюда.



тегистатьи IT, windows, файл, файловая система

Читайте также:




Стек Java
Урок 17. Конвертация чисел в строки (Number в String) C#


© upread.ru 2013-2020
При перепечатке активная ссылка на сайт обязательна.
Задать вопрос
письмо
Здравствуйте! Вы можете задать мне любой вопрос. Если не получается отправить сообщение через эту форму, то пишите на почу up777up@yandex.ru
Отправляя сообщение я подтверждаю, что ознакомлен и согласен с политикой конфиденциальности данного сайта.