Добавил:
Upload Опубликованный материал нарушает ваши авторские права? Сообщите нам.
Вуз: Предмет: Файл:
РГТЭУ инфа экзамен.docx
Скачиваний:
0
Добавлен:
01.05.2025
Размер:
149.71 Кб
Скачать
  1. Организация доступа к файлам.

Для хранения файлов обычно используются устройства прямого доступа (диски), которые позволяют обращаться напрямую к любому блоку диска. Это обеспечивает произвольный доступ к байтам файла, поскольку номер блока однозначно определяетсятекущей позицией внутри файла. Таким образом, файловая подсистема ОС Windows имеет дело с файлами, байты которых могут быть считаны в любом порядке. Такие файлы называется файлами прямого доступа. Непосредственное обращение к любому байту внутри файла предполагает наличие операции позиционирования, целью которой является задание текущей позиции для считывания или записи. Поскольку файл может иметь большой размер, указатель текущей позиции - 64-разрядное число, для задания которого обычно используются два 32-разрядных.

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

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

Для того чтобы воспользоваться возможностями асинхронного ввода-вывода, нужно вызвать функцию CreateFile с установленным флагом FILE_FLAG_OVERLAPPED, входящим в состав параметра dwFlagsAndAttrs, и указать: с какой позиции осуществлять чтение (запись), сколько байтов считать (записать) и какое событие должно сигнализировать о том, что операция завершена. Для этого необходимо проинициализировать поля структуры OVERLAPPED в параметре pOverlapped функций ReadFileили WriteFile.

Структура OVERLAPPED

typedef struct _OVERLAPPED {

ULONG_PTR Internal;

ULONG_PTR InternalHigh;

DWORD Offset;

DWORD OffsetHigh;

HANDLE hEvent;

} OVERLAPPED;

Параметр Internal используется для хранения кода возможной ошибки, а параметр InternalHigh - для хранения числа переданных байт. Вначале разработчики Windows не планировали делать их общедоступными - отсюда и такие не содержащие мнемоники имена. Offset и OffsetHigh - соответственно младшие и старшие разряды текущей позиции файла. hEvent специфицирует событие, сигнализирующее окончание операции ввода-вывода.

Прогон программы, осуществляющей асинхронное чтение из уже существующего файла

#include <windows.h>

#include <stdio.h>

void main(void) {

HANDLE hFile, hHeap;

int iRet = 0;

void *pMem;

long BufSize = 512;

DWORD iRead = 10;

char * String;

OVERLAPPED ov = {0};

hFile = CreateFile("MYFILE.TXT", GENERIC_READ | GENERIC_WRITE, 0, NULL, OPEN_EXISTING,

FILE_ATTRIBUTE_NORMAL | FILE_FLAG_OVERLAPPED, NULL);

if (hFile == INVALID_HANDLE_VALUE) printf("Could not open file.");

hHeap = GetProcessHeap();

pMem = HeapAlloc(hHeap, HEAP_ZERO_MEMORY, BufSize);

String = (char *)pMem;

ov.Offset = 3;

ReadFile(hFile, pMem, iRead, &iRead, &ov);

WaitForSingleObject(hFile, INFINITE);

printf("Read %d bytes: %s\n", iRead, String);

printf("Read %d bytes: %s\n", ov.InternalHigh, String);

HeapFree(hHeap, 0, pMem);

CloseHandle(hFile);

}

В программе проинициализирована структура OVERLAPPED и передана функции ReadFile в качестве параметра. Чтение начинается с 3-й позиции. Узнать число прочитанных байтов можно из ov.InternalHigh - компонента структуры OVERLAPPED. Обратите внимание, что значение переменной iRead, которая должна содержать количество прочтенных байтов, равно 0, так как функция вернула управление до завершения операции ввода-вывода. Обычно это справедливо для первого запуска программы. При последующих запусках, поскольку данные файла находятся в кэше, запрос может успеть выполниться синхронно и значение iRead уже будет равно числу прочитанных байтов.

В программе выбран простейший вариант синхронизации - сигнализация от объекта, управляющего устройством, в данном случае - открытого файла (функцииWaitForSingleObject передан описатель открытого файла в качестве параметра). Существуют и другие, более интересные способы синхронизации, например, использование порта завершения ввода-вывода ( IoCompletitionPort ). Более подробно возможности асинхронного ввода-вывода описаны в [ Рихтер ] , [ Рихтер, Кларк ]и [ Харт ] .

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

Операция позиционирования в случае синхронного доступа к файлу

Итак, в случае асинхронного доступа позиция, начиная с которой будет осуществляться операция чтения-записи, содержится в запросе на операцию (параметр структурыOVERLAPPED ). Рассмотрим теперь особенности позиционирования при обычном синхронном вводе-выводе. В этом случае реализуется схема с "сохранением состояния", 64-разрядный указатель текущей для чтения-записи позиции хранится в составе атрибутов объекта "открытый файл" (его не нужно путать с атрибутами файла), описатель которого возвращает функция CreateFile.

Текущая позиция смещается на конец считанной или записанной последовательности байтов в результате операций чтения или записи. Кроме того, можно установить текущую позицию при помощи Win32-функции SetFilePointer. Например, операция

SetFilePointer(hFile,17 , NULL, FILE_BEGIN);

устанавливает указатель текущей позиции на 17-й байт с начала файла.

Тот факт, что указатель текущей позиции является атрибутом объекта "открытый файл", а не самого файла, означает, что тот же самый файл можно открыть повторно с другим описателем. При этом для одного и того же файла будут существовать два разных объекта с двумя разными указателями текущих позиций. Очевидно, что смена текущей позиции при работе с файлом через разные объекты будет происходить независимо.

С другой стороны, получив описатель открытого файла, можно его продублировать при помощи Win32- функции DuplicateHandle. В этом случае два разных описателя будут ссылаться на один и тот же объект с одним и тем же указателем текущей позиции.

Написание, компиляция и прогон программы, осуществляющей перемещение указателя текущей позиции внутри открытого файла

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