
- •Ввод-вывод в языке с
- •Потоковые функции
- •Открытие файлов и потоков
- •Переадресация ввода-вывода
- •Изменение буфера потока
- •Форматный вывод данных
- •Функция printf()
- •Поиск в файлах с помощью функций fseek( ), ftell( ) и rewind()
- •Синхронный и асинхронный ввод/вывод
- •3. Позиционирование указателя файла.
- •6. Запись данных в файл
- •Блокировка и разблокировка файла
- •Асинхронный режим чтения и записи файлов
- •Стандартные потоки cin, coutи cerr
- •Флаги и функции форматирования
- •Файловый ввод-вывод
- •Флаг Назначение
- •Файловый ввод
- •Файловый вывод
- •Вот результаты работы программы:
- •Двоичные файлы
- •Буферы потоков
Синхронный и асинхронный ввод/вывод
Операция ввода/вывода может выполняться по отношению к программному модулю, запросившему операцию, в
Синхронном режиме.
Асинхронном режиме.
Синхронный режим означает, что поток приостанавливает свою работу до тех пор, пока операция ввода/вывода не будет завершена (рис.1).
В результате поток вызывает сервис ввода/вывода. Устройство заканчивает передачу данных и возвращает программе код завершения. В простейшем случае известные функции API ReadFile() и WriteFile() выполняются синхронно.
Прежде чем возвратить управление вызывающей программе, они заканчивают выполнение операции ввода/вывода (рис.2).
П
ри
асинхронном режиме поток продолжает
выполняться в мультипрограммном режиме
одновременно с операцией ввода/вывода
(рис.3).
Отличие же заключается в том, что операция
ввода/вывода может быть инициирована
не только пользовательским процессом
— в этом случае операция выполняется
в рамках системного вызова, но и кодом
ядра, например кодом системы виртуальной
памяти для считывания отсутствующей в
памяти страницы.
Асинхронный ввод-вывод имеет важное преимущество перед синхронным — возможность повышения скорости работы приложений. Пока устройство занято пересылкой данных, приложение продолжает выполнять другую работу.
В терминологии Win32 "асинхронный" ввод-вывод называется "совмещенным" ("overlapped").
П
осле
начала асинхронной операции ввода/вывода
поток должен
позаб
отиться
о том, чтобы не использовать никаких
данных этой операции
до тех пор, пока драйвер устройства не
завершит ее. Другими словами, поток
должен синхронизировать свое выполнение
с завершением операции ввода/вывода,
ожидая у хэндла файла (рис.4).
Приблизительно треть базовых сервисов Windows, предоставляемых подсистемам диспетчером ввода/вывода, асинхронны по умолчанию.
Асинхронными сервисами являются те, которые, вероятно, будут выполняться долгое или вообще непредсказуемое время. Поток, вызывающий эти сервисы, должен синхронизировать свое выполнение с их завершением.
Хотя некоторые сервисы ведут себя синхронно, а некоторые — асинхронно, сама система ввода/вывода работает полностью асинхронно — от обработки прерываний до передачи результатов обратно пользовательскому режиму и запуска исполнения запроса на устройстве. Асинхронный режим обеспечивает системе ввода/вывода возможность гибко переключаться на другие задачи, пока относительно медленные устройства пересылают данные. Асинхронные вызовы процедур (АРС) — другое средство Windows и асинхронного ввода/вывода Win32.
Использование асинхронных процедур приводит к более гибким решениям, так как на основе асинхронного вызова всегда можно построить синхронный, создав дополнительную промежуточную процедуру, блокирующую выполнение вызвавшей процедуры до момента завершения ввода/вывода. Иногда и прикладному процессу требуется выполнить асинхронную операцию ввода/вывода, например при микроядерной архитектуре, когда часть кода работает в пользовательском режиме как прикладной процесс, но выполняет функции операционной системы, требующие полной свободы действий и после вызова операции ввода/вывода.
РЕАЛИЗАЦИЯ СИНХРОННОГО И АСИНХРОННОГО ВВОДА/ВЫВОДА СРЕДСТВАМИ WIN32 API
Синхронный режим чтения и записи файлов
Процесс выборки данных при синхронном вводе-выводе выглядит следующим образом:
Выделение в памяти буфера определённого размера.
Открытие файл, к которому он намерен обращаться.
Установка указатель файла на то место в файле, где находятся требуемые данные.
Считывание данных из файла в буфер.
Выполнение действий над данными из буфера.
Запись буфера на то же место в файле или добавляется в конец файла.
Естественно, что в реальной ситуации те или иные шаги могут быть опущены. Но для полноты рассмотрим все возможные шаги.
1. Выделение в памяти буфера рассматривалось ранее, и останавливаться на нем не будем.
2. Открытие файла производиться с помощью функции CreateFile().
Функция CreateFile() имеет синтаксис следующий.
HANDLE CreateFile (LPCTSTR lpFileName, DWORD dwDesiredAccess, DWORD dwShareMode, LPSECURITY_ATTRIBUTES lpSecurityAttributes, DWORD dwCreationDistribution, DWORD dwFlagsAndAttributes, HANDLE hTemplateFile )
Параметры:
lpFileName – указатель на строку имени файла (канала).
dwDesiredAccess – режим доступа.
dwShareMode – режим совместного использования файла.
lpSecurityAttributes – указатель на атрибуты защиты
dwCreationDistribution – параметры создания.
dwFlagsAndAttributes – атрибуты файла.
hTemplateFile – хэндл файла с атрибутами.
Возвращаемое значение. При успешном выполнении – хэндл созданной реализации канала, при ошибке – INVALID_HANDLE_VALUE. Код ошибки уточняется при вызове функции GetLastError().
При работе с файлами в первом параметре lpFileName задается адрес строки, содержащей имя файла, который собираются создать или открыть. Строка должна быть закрыта двоичным нулем. Если функция CreateFile() работает с каналом Pipe, параметр lpFileName определяет имя канала.
Второй параметр dwDesiredAccess определяет тип доступа, который должен быть предоставлен к открываемому файлу (каналу). Здесь используя логическую комбинацию следующих констант можно получить:
Константа |
Описание |
0 |
Доступ запрещен, однако приложение может определять атрибуты файла, канала или устройства, открываемого при помощи функции CreateFile() |
GENERIC_READ |
Разрешен доступ на чтение из файла или канала Pipe |
GENERIC_WRITE |
Разрешен доступ на запись в файл или канал Pipe |
Тип доступа, указанный при помощи параметра dwDesiredAccess, не должен противоречить типу доступа для канала, заданного при его создании функцией CreateNamedPipe().
С помощью третьего параметра dwShareMode задаются режимы совместного использования открываемого или создаваемого файла. Для этого параметра также можно указать логическую комбинацию следующих констант:
Константа |
Описание |
0 |
Совместное использование файла запрещено |
FILE_SHARE_READ |
Другие процессы могут открывать файл с помощью функции CreateFile() для чтения |
FILE_SHARE_WRITE |
Другие процессы могут открывать файл с помощью функции CreateFile() на запись |
Через четвертый параметр lpSecurityAttributes необходимо передать указатель на дескриптор защиты или значение NULL, если этот дескриптор не используется.
Пятый параметр dwCreationDistribution определяет действия, выполняемые функцией CreateFile(), если приложение пытается создать файл, который уже существует. Для этого параметра вы можете указать одну из следующих констант:
Константа |
Описание |
CREATE_NEW |
Если создаваемый файл уже существует, функция CreateFile() возвращает код ошибки |
CREATE_ALWAYS |
Существующий файл перезаписывается, при этом содержимое старого файла теряется |
OPEN_EXISTING |
Открывается существующий файл. Если файл с указанным именем не существует, функция CreateFile() возвращает код ошибки |
OPEN_ALWAYS |
Если указанный файл существует, он открывается. Если файл не существует, он будет создан |
TRUNCATE_EXISTING |
Если файл существует, он открывается, после чего длина файла устанавливается равной нулю. Содержимое старого файла теряется. Если же файл не существует, функция CreateFile() возвращает код ошибки |
Шестой параметр dwFlagsAndAttributes задает атрибуты и флаги для файла. При этом можно использовать любые логические комбинации следующих флагов (кроме флага FILE_ATTRIBUTE_NORMAL, который можно использовать только отдельно):
Атрибут |
Описание |
FILE_ATTRIBUTE_ARCHIVE |
Файл был архивирован (выгружен) |
FILE_ATTRIBUTE_COMPRESSED |
Файл, имеющий этот атрибут, динамически сжимается при записи и восстанавливается при чтении. Если этот атрибут имеет каталог, то для всех расположенных в нем файлов и каталогов также выполняется динамическое сжатие данных |
FILE_ATTRIBUTE_NORMAL |
Остальные перечисленные в этом списка атрибуты не установлены |
FILE_ATTRIBUTE_HIDDEN |
Скрытый файл |
FILE_ATTRIBUTE_READONLY |
Файл можно только читать |
FILE_ATTRIBUTE_SYSTEM |
Файл является частью операционной системы |
В дополнение к перечисленным выше атрибутам, через параметр dwFlagsAndAttributes вы можете передать любую логическую комбинацию флагов, перечисленных ниже:
Флаг |
Описание |
FILE_FLAG_WRITE_THROUGH |
Отмена промежуточного кэширования данных для уменьшения вероятности потери данных при аварии |
FILE_FLAG_NO_BUFFERING |
Отмена промежуточной буферизации или кэширования. При использовании этого флага необходимо выполнять чтение и запись порциями, кратными размеру сектора (обычно 512 байт) |
FILE_FLAG_OVERLAPPED |
Асинхронное выполнение чтения и записи. Во время асинхронного чтения или записи приложение может продолжать обработку данных |
FILE_FLAG_RANDOM_ACCESS |
Указывает, что к файлу будет выполняться произвольный доступ. Флаг предназначен для оптимизации кэширования |
FILE_FLAG_SEQUENTIAL_SCAN |
Указывает, что к файлу будет выполняться последовательный доступ от начала файла к его концу. Флаг предназначен для оптимизации кэширования |
FILE_FLAG_DELETE_ON_CLOSE |
Файл будет удален сразу после того как приложение закроет его идентификатор. Этот флаг удобно использовать для временных файлов |
FILE_FLAG_BACKUP_SEMANTICS |
Файл будет использован для выполнения операции выгрузки или восстановления. При этом выполняется проверка прав доступа |
FILE_FLAG_POSIX_SEMANTICS |
Доступ к файлу будет выполняться в соответствии со спецификацией POSIX (в частности, в этом случае могут употребляться файлы, имена которых различаются только регистром букв) |
И, наконец, седьмой параметр hTemplateFile предназначен для доступа к файлу шаблона с расширенными атрибутами создаваемого файла.