Типовая совокупность действий пользователя в отношении файловой системы на диске состоит из форматирования диска, создания на нем структуры каталогов, заполнения их файлами, а также выполнения разнообразных действий с этими файлами. В предыдущей лекции говорилось главным образом о том, какие возможности предоставляет файловая система пользователю для решения его задач. Теперь перейдем к рассмотрению вопросов, которые связаны с реализацией предоставляемых сервисов, алгоритмами и структурами данных на диске, позволяющими связать символьное имя файла с данными. Кроме того,
Нижний уровень в системе хранения данных - диски с подвижными головками. Для обмена с магнитным диском на уровне аппаратуры нужно указать номер цилиндра, номер поверхности, номер блока на соответствующей дорожке и число байтов, которое нужно записать или прочитать от начала этого блока. Таким образом, диски могут быть разбиты на блоки фиксированного размера, и можно непосредственно получить доступ к любому блоку (организовать прямой доступ к файлам).
В традиционной многоуровневой системе построения операционных систем с устройствами (дисками) непосредственно взаимодействует часть ОС, называемая системой ввода-вывода, основу которой составляют драйверы устройств. Задача системы ввода-вывода: скрыть особенности работы с дисками и предоставить в распоряжение более высокоуровневого компонента ОС - файловой системы - используемое дисковое пространство в виде непрерывной последовательности блоков фиксированного размера. Файловая система располагается соответственно между системой ввода-вывода и прикладной программой см., например, .
(рис 12.1) В ОС Windows файловая система интегрирована в систему ввода-вывода (см. , . В данной лекции речь пойдет о ее файловой подсистеме.
Обычно диски разбиты на блоки (секторы) размером - 512 б. Однако удобнее оперировать блоками более крупного размера - кластерами (cluster). format.
Ниже приведена часть результатов вывода команды "format /?"
ключ: /A:размер
Заменяет
NTFS поддерживает размеры 512, 1024, 2048, 4096, 8192, 16КБ, 32КБ, 64K.
Файловые системы FAT и
FAT: число кластеров <= 65526
Выполнение команды Format будет немедленно прервано, если будет обнаружено нарушение указанных выше ограничений, используя указанный
Сжатие томов NTFS не поддерживается для
Система различает кластеры диска (volume claster) и кластеры диска, принадлежащие файлу (logical claster). Для них поддерживается разная нумерация, соответственно
Основная функция файловой системы - связь символьного имени файла и блоков диска, принадлежащих файлу, - реализуется с помощью ссылки из записи каталога о данном файле на запись в таблице, формат которой определяется типом файловой системы на данном диске.
Например, в файловой системе FAT, одной из файловых систем, поддерживаемых ОС Windows, имеется таблица отображения файлов (file allocation table), которая поддерживает связный список блоков для каждого файла. Таблица индексирована по номерам блоков. Запись в каталоге указывает на строку в таблице, содержащую первый блок файла, а далее по таблице можно найти все остальные блоки данного файла. Принцип работы файловой системы FAT более подробно описан в .
Рассмотрим устройство базовой файловой системы ОС Windows - NTFS.
В файловой системе NTFS запись о файле в каталоге сопоставляется с записью о файле в главной файловой таблице диска -
(рис 12.2) Записи MFTВ состав каждой записи входит заголовок и последовательность пар <заголовок атрибута, значение>. Если атрибут целиком помещается в записи
Чаще данные файла все же не помещаются в записи
(рис 12.3) Запись MFT для 10-блочного файла, состоящего из четырех фрагментов (серий)Напомним, что решается задача приведения в соответствие номера блока в файле (
Для сильно фрагментированных файлов требуется много серий и несколько
Номера дисковых кластеров файлов можно узнать при помощи утилиты nfi.exe (NTFS File
\TMP\Nfi\exp.h
$STANDARD_INFORMATION (resident)
$FILE_NAME (resident)
$DATA (nonresident)
logical sectors 471790-471794 (0x732ee-0x732f2)
File 33
\TMP\Nfi\h.h
$STANDARD_INFORMATION (resident)
$FILE_NAME (resident)
$DATA (nonresident)
logical sectors 471798-471809 (0x732f6-0x73301)
Здесь приведена информация о файлах \tmp\nfi\exp.h и \tmp\nfi\h.h, которую выдает утилита nfi .
Наиболее интересно расположение на диске нерезидентного атрибута потока данных, дисковые номера кластеров которого в данном случае обозначаются как logical
В системе Windows учет свободных и занятых дисковых блоков ведется при помощи 00111100111100011000001, где каждый блок представлен одним битом, принимающим значение 0 или 1, в зависимости от того, занят он или свободен. В файловой системе NTFS
Как уже говорилось, директория или каталог - это файл, имеющий вид таблицы и хранящий список входящих в него файлов или каталогов. Основная задача файлов-директорий - поддержка иерархической древовидной структуры файловой системы.
Как и любому файлу, каталогу соответствует запись в таблице
(рис 12.4) MFT запись для небольшого каталогаДля больших каталогов совокупность записей о файлах не помещается в
Поиск файла на диске - стандартная задача, которую приходится решать любому работающему с файлами приложению уже на этапе открытия файла. Поисковые программы прибегают для этих целей к специализированным API-функциям поиска файлов.
При поиске файла вначале при помощи механизма символьных ссылок в пространстве имен объектов решается задача трансляции имени диска "в стиле DOS" или буквы диска во внутренние имена устройств Windows. Для этого библиотечный вызов, содержащий имя файла в качестве параметра, передается библиотеке .
(рис 12.5) Процесс поиска файла по имениДля поиска файлов в каталоге применяются функции FindFirstFile и FindNextFile (см. MSDN).
Приведенная программа выводит список файлов в каталоге с заданным шаблоном поиска. Информация о найденных файлах содержится в структуре WIN32_FIND_DATA, которая является одним из параметров функций FindFirstFile и FindNextFile. Входным параметром функции FindFirstFile служит шаблон поиска, а выходным - дескриптор поиска, который является входным параметром функции FindNextFile и хранит информацию о текущем состоянии поиска (аналог FindClose (а не CloseHandle как обычно).
Современные операционные системы обычно предоставляют в распоряжение пользователя типовые возможности для монтирования файловых систем и образования жестких и символических связей. Эта функциональность в ОС Windows реализуется при помощи механизма, называемого точками повторного анализа. Если файл помечен как точка повторного анализа, то в составе его атрибутов присутствует флаг FILE_ATTRIBUTE_REPARSE_POINT. Обычно с этим файлом ассоциирован блок данных, которые могут быть считаны и интерпретированы приложением, создавшим эту точку, или драйвером ОС.
Операция HKLM\SYSTEM\MountedDevices.
Создание точек монтирования (mount points) - связывание каталога NTFS реализовано с помощью точек повторного анализа. Программы, осуществляющие навигацию по каталогам, должны, обнаружив точку повторного анализа (в данном случае точку монтирования), прибегнуть к помощи кода, направляющего процесс дальнейшей навигацию на новый том. Программы, предоставляющие информацию о суммарном количестве файлов на диске или в каталоге, также должны учитывать наличие точек монтирования.
Точки монтирования в системе можно найти при помощи Win32-функций FindFirstVolumeMountPoint и FindNextVolumeMountPoint.
Связывание файлов - техника, заимствованная из Unix, - образование для файла или каталога нескольких
(рис 12.6) Образование связей в файловой системеСоединение между директорией и разделяемым файлом называется "связью" или "ссылкой" (link). Дерево файловой системы превращается в циклический граф.
ОС Windows (как и Unix) поддерживает два вида связей - жесткие (hard link) и символические (
Символическая линковка - создание нового файла, который содержит путь к связываемому файлу. Обычно в системе создается каталог, который связывается с уже существующим каталогом. Этот метод удобен для "подъема" (уменьшения степени
CreateHardLink. Штатной утилиты, поддерживающей
Символическую связь (иногда говорят точку соединения,
Тот факт, что операции монтирования и связывания могут превратить иерархическое дерево файловой системы в циклический граф, делает работу с ней более сложной. Поскольку теперь к файлу существует несколько путей, программа поиска файла может найти его на диске несколько раз. Простейшее практическое решение данной проблемы - ограничить число директорий при поиске. С этой целью при поиске файлов Windows Explorer останавливает рекурсию по достижении 32-го уровня вложенности или при превышении длины пути в 256 символов. Это зависит от того, какое событие наступит раньше..
Полное устранение циклов при поиске - довольно трудоемкая процедура, выполняемая специальными утилитами и связанная с многократной трассировкой директорий файловой системы.
Образование циклического графа можно проиллюстрировать на примере образования рекурсивной точки монтирования.
Эксперимент
Создайте на диске X: каталог Recurse и смонтируйте его с корневым каталогом диска X: Затем для этого каталога выполните команду dir /s.
Создайте пустой каталог и сделайте его точкой монтирования или символической связью. При помощи функции GetFileAttributes установите у данного каталога наличие флага FILE_ATTRIBUTE_REPARSE_POINT.
Пользователи часто нуждаются в разделении файлов и совместном доступе к ним.
Как уже было сказано выше, операция открытия файла имеет следствием создание объекта "открытый файл". Специфика объекта "открытый файл" состоит в том, что он содержит лишь уникальные данные (например, указатель текущей позиции), тогда как собственно файл - совместно используемые данные. Поэтому, если два раза осуществить операцию открытия одного и того же файла, то система создаст два объекта "файл". Данная ситуация проиллюстрирована рис 12.7 для случая одновременного открытия файла потоками разных процессов.
(рис 12.7) Организация совместного доступа к файлуОчевидно, что потоки должны синхронизировать доступ к совместно используемым файлам или каталогам, чтобы получить предсказуемый результат. Между двумя операциями read одного потока другой поток может модифицировать данные, что для многих приложений неприемлемо. ОС Windows предлагает LockFile и UnlockFile.
Несмотря на то, что у данного механизма захвата файла непростая логика и наследование (см., например ), рекомендуется самостоятельно разработать небольшую программу, иллюстрирующую данный способ синхронизации. Программа должна продемонстрировать невозможность осуществления операции записи одним процессом в файл, заблокированный другим процессом при помощи функции LockFile.
Эффективность работы - одна из важнейших задач подсистемы управления файлами.
Самый естественный способ повысить производительность - минимизировать количество обращений к диску за счет кэширования. В общем случае кэширование - использование быстрого устройства для оптимизации работы устройства медленного. В данном случае часть блоков файла, с которыми активно взаимодействует приложение, размещается в буфере оперативной памяти. Периодически производится синхронизация содержимого кэша и диска. Возможность использования кэша в операционных системах обусловлена свойством локальности - объем ключевой информации в каждый момент времени относительно невелик.
Устройство кэша ОС Windows отличается от традиционного. В традиционной реализации кэш - буфер в оперативной памяти, содержащий ряд блоков диска и расположенный между файловой системой и системой ввода-вывода. Если имеется запрос на чтение (запись) в файл, файловая система вычисляет номер блока в файле и номер соответствующего ему блока диска. Перед чтением/записью блока диска производится проверка на предмет наличия этого блока в кэше. Если блок в кэше имеется, то запрос удовлетворяется из кэша, в противном случае запрошенный блок считывается в кэш с диска.
В ОС Windows кэш работает на более высоком уровне, нежели файловая система (см. рис 12.8).
(рис 12.8) Место менеджера кэша в системе ввода-выводаС помощью техники файлов, отображаемых в память, часть считываемого (записываемого) файла проецируется в 256-килобайтный буфер кэша (см. рис 12.9).
(рис 12.9) Файлы различного размера, спроецированные в системный кэш В результате запрос на чтение с текущей позиции может быть непосредственно удовлетворен из кэша. Если же нужных байтов файла в кэше нет, то файловая система вычисляет логический номер блока в файле (
Важным свойством кэша является его когерентность. Менеджер кэша следит за соответствием открытых файлов и файлов, отображаемых в память (с помощью функции MapViewOfFile ). Каждый раз, когда процесс считывает файл или отображает его в память, этот запрос удовлетворяется из кэша путем копирования соответствующего блока в
Аккуратная реализация кэширования требует решения нескольких проблем.
Во-первых, емкость буфера кэша ограничена. У системного кэша нет собственного рабочего набора - он входит в единый системный рабочий набор. Размером системного рабочего набора управляет менеджер памяти, отвечающий за его расширение или усечение. При этом величина, помеченная как размер системного кэша на панели диспетчера задач, относится к размеру всего системного рабочего набора.
Во-вторых, поскольку кэширование использует механизм отложенной записи (
Записываемые данные в течение некоторого времени накапливаются, после чего сбрасываются на диск пакетом. С точки зрения быстродействия и снижения риска от возможных потерь очень важен выбор частоты сброса кэша. Обычно подсистема отложенной записи раз в секунду сбрасывает на диск одну восьмую количества модифицированных страниц системного кэша.
ОС Windows позволяет организовать вариант синхронного режима работы с отдельными файлами, задаваемый при открытии файла, при котором все изменения в файле немедленно сохраняются на диске. Для этого можно, например, установить флаг FILE_FLAG_WRITE_THROUGH при вызове функции CreateFile. Фактически, это отказ от кэширования и, соответственно, резкое снижение производительности.
Кроме того в любой момент можно принудительно сбросить содержимое кэша открытого файла на диск с помощью функции FlushFileBuffers. Напомним, что для отображаемого файла имеется аналогичная функция FlushViewOfFile.
#include <windows.h>
#include <stdio.h>
void main(void) {
HANDLE hFile, hHeap;
int iRet = 0;
void *pMem;
long FileSize = 0, FilePos = 0;
DWORD iRead = 0, iWrite = 0;
char * String;
hFile = CreateFile("MYFILE.TXT", GENERIC_READ| GENERIC_WRITE,0,
NULL, OPEN_EXISTING,FILE_ATTRIBUTE_NORMAL |0, NULL);
if (hFile == INVALID_HANDLE_VALUE) printf("Could not open file \n");
FileSize = GetFileSize(hFile, NULL);
printf("FileSize = %d\n",FileSize);
hHeap = GetProcessHeap();
pMem = HeapAlloc(hHeap, HEAP_ZERO_MEMORY, FileSize + 2);
String = (char *)pMem;
ReadFile(hFile, pMem, FileSize, iRead, NULL);
printf("Read %d bytes \n", iRead);
for(FilePos = 0; FilePos < FileSize; FilePos++)
String[FilePos] = '1';
SetFilePointer(hFile, 0, NULL, FILE_BEGIN);
getchar();
WriteFile(hFile, pMem, FileSize, iWrite, NULL);
printf("Write %d bytes \n", iWrite);
iRet = FlushFileBuffers(hFile);
if(iRet == 0) printf("FlushFileBuffer Error\n");
HeapFree(hHeap, 0, pMem);
CloseHandle(hFile);
}
Приведенная программа считывает большой файл (рекомендуемый размер - несколько мегабайт) в буфер памяти. Затем она меняет содержимое буфера и записывает его на диск. При этом программа пытается сбросить содержимое кэша с помощью функции FlushFileBuffers.
За результатами работы программы можно наблюдать с помощью счетчика "сбросов данных" кэша. Счетчик ведет себя в соответствии с рисунком, где максимальный пик появляется вслед за нажатием клавиши "Enter".
(рис 12.10) Поведение счетчика "сбросов данных" кэшаРекомендуется модифицировать данную программу и проанализировать поведение системы отложенного сброса кэша при помощи соответствующих счетчиков производительности.
Кэширование - не единственный способ увеличения производительности системы. Другая важная техника - сокращение количества движений считывающей головки диска за счет разумной
Поскольку разрушение файловой системы зачастую более опасно, чем разрушение компьютера, файловые системы должны разрабатываться с учетом подобной возможности. Сохранность информации может быть обеспечена за счет ее избыточности (резервное копирование, зеркалирование, образование RAID массивов). Файловые системы современных ОС содержат специальные средства для поддержки собственной целостности и непротиворечивости.
Как правило, файловая операция затрагивает сразу несколько объектов файловой системы. Например, запись в файл предполагает выделение ему блоков диска, модификацию
Для обозначения совокупности действий, выполняемых файловой операцией, используется термин транзакция. Очевидно, что для сохранения целостности файловой системы транзакция должна выполняться целиком или не выполняться вообще.
Одним из средств поддержки целостности является журналирование. Последовательность действий с объектами во время транзакции протоколируется, и, если произошел останов системы, то, имея в наличии протокол, можно осуществить откат системы назад в исходное целостное состояние, в котором она пребывала до начала транзакции.
В журнал заносятся не все изменения, а лишь изменения метаданных (
Для файла-журнала отводится вторая запись таблицы
Применяемая схема - это результат компромисса между полной отказоустойчивостью системы и максимальной производительностью файловых операций. Разумеется, в распоряжении пользователя остаются средства организации сквозной записи на диск и принудительного сброса на диск кэша NTFS ( FlushFileBuffer ).
Если нарушение целостности файловой системы все же произошло, то можно прибегнуть к помощи специализированных утилит (chkdsk, scandisk и др.). Они могут запускаться после загрузки или после сбоя и осуществляют многократное сканирование разнообразных структур данных файловой системы в поисках противоречий.
Наличие дефектных блоков на диске - обычное дело. Под "плохими" блоками обычно понимают блоки диска, для которых вычисленная контрольная сумма считываемых данных не совпадает с хранимой контрольной суммой. В NTFS применяется один из способов нейтрализации данной проблемы - конструирование файла, содержащего дефектные блоки. Для этого файла зарезервирована запись 8 в таблице
Для решения ряда проблем необходимо уметь фиксировать изменения файловой системы по истечении некоторого промежутка времени. Например, обнаружение нарушения целостности файлов, содержащих компоненты самой операционной системы, является способом защиты от внешнего навязывания и одним из средств повышения общей безопасности системы (см. лекцию 15 ). Другим примером может быть актуализация сведений о файлах в диалогах и окнах программ, работающих с файлами.
Для решения подобных задач ОС Windows располагает самыми широкими возможностями. Для знакомства с данной техникой рекомендуется изучить работу программных примеров из MSDN (см. раздел MSDN Using File I/O), или особенности применения функции FindFirstChangeNotification.
Подобно многим современным операционным системам ОС Windows поддерживает несколько файловых систем (
Код, реализующий функциональность каждой файловой подсистемы ОС, входит в состав соответствующего драйвера файловой системы. Запрос прикладной программы на чтение (запись) из файла передается диспетчеру ввода-вывода, который пытается обслужить этот запрос с помощью единого интегрированного кэша (см. рис 12.8).
Если нужная информация в кэше отсутствует, диспетчер ввода-вывода обращается к устройству, содержащему данный файл, подбирая драйвер, соответствующий данному устройству. Драйвер конкретной файловой системы по имени файла и байтовому смещению определяет номер блока на диске и переадресует запрос на обработку этого блока драйверу диска.
Помимо кэша драйверы файловых систем тесно интегрированы с диспетчером памяти, что позволяет обеспечить корректность и когерентность механизма проецирования файлов в память.
Настоящая лекция описывает отдельные аспекты реализации файловой системы NTFS. Главная функция файловой системы - связь символьного имени с блоками диска - реализована за счет поддержки списка блоков в записи о файле в главной файловой таблице
Типовая совокупность действий пользователя в отношении файловой системы на диске состоит из форматирования диска, создания на нем структуры каталогов, заполнения их файлами, а также выполнения разнообразных действий с этими файлами. В предыдущей лекции говорилось главным образом о том, какие возможности предоставляет файловая система пользователю для решения его задач. Теперь перейдем к рассмотрению вопросов, которые связаны с реализацией предоставляемых сервисов, алгоритмами и структурами данных на диске, позволяющими связать символьное имя файла с данными. Кроме того,
Нижний уровень в системе хранения данных - диски с подвижными головками. Для обмена с магнитным диском на уровне аппаратуры нужно указать номер цилиндра, номер поверхности, номер блока на соответствующей дорожке и число байтов, которое нужно записать или прочитать от начала этого блока. Таким образом, диски могут быть разбиты на блоки фиксированного размера, и можно непосредственно получить доступ к любому блоку (организовать прямой доступ к файлам).
В традиционной многоуровневой системе построения операционных систем с устройствами (дисками) непосредственно взаимодействует часть ОС, называемая системой ввода-вывода, основу которой составляют драйверы устройств. Задача системы ввода-вывода: скрыть особенности работы с дисками и предоставить в распоряжение более высокоуровневого компонента ОС - файловой системы - используемое дисковое пространство в виде непрерывной последовательности блоков фиксированного размера. Файловая система располагается соответственно между системой ввода-вывода и прикладной программой см., например, .
(рис 12.1) В ОС Windows файловая система интегрирована в систему ввода-вывода (см. , . В данной лекции речь пойдет о ее файловой подсистеме.
Обычно диски разбиты на блоки (секторы) размером - 512 б. Однако удобнее оперировать блоками более крупного размера - кластерами (cluster). format.
Ниже приведена часть результатов вывода команды "format /?"
ключ: /A:размер
Заменяет
NTFS поддерживает размеры 512, 1024, 2048, 4096, 8192, 16КБ, 32КБ, 64K.
Файловые системы FAT и
FAT: число кластеров <= 65526
Выполнение команды Format будет немедленно прервано, если будет обнаружено нарушение указанных выше ограничений, используя указанный
Сжатие томов NTFS не поддерживается для
Система различает кластеры диска (volume claster) и кластеры диска, принадлежащие файлу (logical claster). Для них поддерживается разная нумерация, соответственно
Основная функция файловой системы - связь символьного имени файла и блоков диска, принадлежащих файлу, - реализуется с помощью ссылки из записи каталога о данном файле на запись в таблице, формат которой определяется типом файловой системы на данном диске.
Например, в файловой системе FAT, одной из файловых систем, поддерживаемых ОС Windows, имеется таблица отображения файлов (file allocation table), которая поддерживает связный список блоков для каждого файла. Таблица индексирована по номерам блоков. Запись в каталоге указывает на строку в таблице, содержащую первый блок файла, а далее по таблице можно найти все остальные блоки данного файла. Принцип работы файловой системы FAT более подробно описан в .
Рассмотрим устройство базовой файловой системы ОС Windows - NTFS.
В файловой системе NTFS запись о файле в каталоге сопоставляется с записью о файле в главной файловой таблице диска -
(рис 12.2) Записи MFTВ состав каждой записи входит заголовок и последовательность пар <заголовок атрибута, значение>. Если атрибут целиком помещается в записи
Чаще данные файла все же не помещаются в записи
(рис 12.3) Запись MFT для 10-блочного файла, состоящего из четырех фрагментов (серий)Напомним, что решается задача приведения в соответствие номера блока в файле (
Для сильно фрагментированных файлов требуется много серий и несколько
Номера дисковых кластеров файлов можно узнать при помощи утилиты nfi.exe (NTFS File
\TMP\Nfi\exp.h
$STANDARD_INFORMATION (resident)
$FILE_NAME (resident)
$DATA (nonresident)
logical sectors 471790-471794 (0x732ee-0x732f2)
File 33
\TMP\Nfi\h.h
$STANDARD_INFORMATION (resident)
$FILE_NAME (resident)
$DATA (nonresident)
logical sectors 471798-471809 (0x732f6-0x73301)
Здесь приведена информация о файлах \tmp\nfi\exp.h и \tmp\nfi\h.h, которую выдает утилита nfi .
Наиболее интересно расположение на диске нерезидентного атрибута потока данных, дисковые номера кластеров которого в данном случае обозначаются как logical
В системе Windows учет свободных и занятых дисковых блоков ведется при помощи 00111100111100011000001, где каждый блок представлен одним битом, принимающим значение 0 или 1, в зависимости от того, занят он или свободен. В файловой системе NTFS
Как уже говорилось, директория или каталог - это файл, имеющий вид таблицы и хранящий список входящих в него файлов или каталогов. Основная задача файлов-директорий - поддержка иерархической древовидной структуры файловой системы.
Как и любому файлу, каталогу соответствует запись в таблице
(рис 12.4) MFT запись для небольшого каталогаДля больших каталогов совокупность записей о файлах не помещается в
Поиск файла на диске - стандартная задача, которую приходится решать любому работающему с файлами приложению уже на этапе открытия файла. Поисковые программы прибегают для этих целей к специализированным API-функциям поиска файлов.
При поиске файла вначале при помощи механизма символьных ссылок в пространстве имен объектов решается задача трансляции имени диска "в стиле DOS" или буквы диска во внутренние имена устройств Windows. Для этого библиотечный вызов, содержащий имя файла в качестве параметра, передается библиотеке .
(рис 12.5) Процесс поиска файла по имениДля поиска файлов в каталоге применяются функции FindFirstFile и FindNextFile (см. MSDN).
Приведенная программа выводит список файлов в каталоге с заданным шаблоном поиска. Информация о найденных файлах содержится в структуре WIN32_FIND_DATA, которая является одним из параметров функций FindFirstFile и FindNextFile. Входным параметром функции FindFirstFile служит шаблон поиска, а выходным - дескриптор поиска, который является входным параметром функции FindNextFile и хранит информацию о текущем состоянии поиска (аналог FindClose (а не CloseHandle как обычно).
Современные операционные системы обычно предоставляют в распоряжение пользователя типовые возможности для монтирования файловых систем и образования жестких и символических связей. Эта функциональность в ОС Windows реализуется при помощи механизма, называемого точками повторного анализа. Если файл помечен как точка повторного анализа, то в составе его атрибутов присутствует флаг FILE_ATTRIBUTE_REPARSE_POINT. Обычно с этим файлом ассоциирован блок данных, которые могут быть считаны и интерпретированы приложением, создавшим эту точку, или драйвером ОС.
Операция HKLM\SYSTEM\MountedDevices.
Создание точек монтирования (mount points) - связывание каталога NTFS реализовано с помощью точек повторного анализа. Программы, осуществляющие навигацию по каталогам, должны, обнаружив точку повторного анализа (в данном случае точку монтирования), прибегнуть к помощи кода, направляющего процесс дальнейшей навигацию на новый том. Программы, предоставляющие информацию о суммарном количестве файлов на диске или в каталоге, также должны учитывать наличие точек монтирования.
Точки монтирования в системе можно найти при помощи Win32-функций FindFirstVolumeMountPoint и FindNextVolumeMountPoint.
Связывание файлов - техника, заимствованная из Unix, - образование для файла или каталога нескольких
(рис 12.6) Образование связей в файловой системеСоединение между директорией и разделяемым файлом называется "связью" или "ссылкой" (link). Дерево файловой системы превращается в циклический граф.
ОС Windows (как и Unix) поддерживает два вида связей - жесткие (hard link) и символические (
Символическая линковка - создание нового файла, который содержит путь к связываемому файлу. Обычно в системе создается каталог, который связывается с уже существующим каталогом. Этот метод удобен для "подъема" (уменьшения степени
CreateHardLink. Штатной утилиты, поддерживающей
Символическую связь (иногда говорят точку соединения,
Тот факт, что операции монтирования и связывания могут превратить иерархическое дерево файловой системы в циклический граф, делает работу с ней более сложной. Поскольку теперь к файлу существует несколько путей, программа поиска файла может найти его на диске несколько раз. Простейшее практическое решение данной проблемы - ограничить число директорий при поиске. С этой целью при поиске файлов Windows Explorer останавливает рекурсию по достижении 32-го уровня вложенности или при превышении длины пути в 256 символов. Это зависит от того, какое событие наступит раньше..
Полное устранение циклов при поиске - довольно трудоемкая процедура, выполняемая специальными утилитами и связанная с многократной трассировкой директорий файловой системы.
Образование циклического графа можно проиллюстрировать на примере образования рекурсивной точки монтирования.
Эксперимент
Создайте на диске X: каталог Recurse и смонтируйте его с корневым каталогом диска X: Затем для этого каталога выполните команду dir /s.
Создайте пустой каталог и сделайте его точкой монтирования или символической связью. При помощи функции GetFileAttributes установите у данного каталога наличие флага FILE_ATTRIBUTE_REPARSE_POINT.
Пользователи часто нуждаются в разделении файлов и совместном доступе к ним.
Как уже было сказано выше, операция открытия файла имеет следствием создание объекта "открытый файл". Специфика объекта "открытый файл" состоит в том, что он содержит лишь уникальные данные (например, указатель текущей позиции), тогда как собственно файл - совместно используемые данные. Поэтому, если два раза осуществить операцию открытия одного и того же файла, то система создаст два объекта "файл". Данная ситуация проиллюстрирована рис 12.7 для случая одновременного открытия файла потоками разных процессов.
(рис 12.7) Организация совместного доступа к файлуОчевидно, что потоки должны синхронизировать доступ к совместно используемым файлам или каталогам, чтобы получить предсказуемый результат. Между двумя операциями read одного потока другой поток может модифицировать данные, что для многих приложений неприемлемо. ОС Windows предлагает LockFile и UnlockFile.
Несмотря на то, что у данного механизма захвата файла непростая логика и наследование (см., например ), рекомендуется самостоятельно разработать небольшую программу, иллюстрирующую данный способ синхронизации. Программа должна продемонстрировать невозможность осуществления операции записи одним процессом в файл, заблокированный другим процессом при помощи функции LockFile.
Эффективность работы - одна из важнейших задач подсистемы управления файлами.
Самый естественный способ повысить производительность - минимизировать количество обращений к диску за счет кэширования. В общем случае кэширование - использование быстрого устройства для оптимизации работы устройства медленного. В данном случае часть блоков файла, с которыми активно взаимодействует приложение, размещается в буфере оперативной памяти. Периодически производится синхронизация содержимого кэша и диска. Возможность использования кэша в операционных системах обусловлена свойством локальности - объем ключевой информации в каждый момент времени относительно невелик.
Устройство кэша ОС Windows отличается от традиционного. В традиционной реализации кэш - буфер в оперативной памяти, содержащий ряд блоков диска и расположенный между файловой системой и системой ввода-вывода. Если имеется запрос на чтение (запись) в файл, файловая система вычисляет номер блока в файле и номер соответствующего ему блока диска. Перед чтением/записью блока диска производится проверка на предмет наличия этого блока в кэше. Если блок в кэше имеется, то запрос удовлетворяется из кэша, в противном случае запрошенный блок считывается в кэш с диска.
В ОС Windows кэш работает на более высоком уровне, нежели файловая система (см. рис 12.8).
(рис 12.8) Место менеджера кэша в системе ввода-выводаС помощью техники файлов, отображаемых в память, часть считываемого (записываемого) файла проецируется в 256-килобайтный буфер кэша (см. рис 12.9).
(рис 12.9) Файлы различного размера, спроецированные в системный кэш В результате запрос на чтение с текущей позиции может быть непосредственно удовлетворен из кэша. Если же нужных байтов файла в кэше нет, то файловая система вычисляет логический номер блока в файле (
Важным свойством кэша является его когерентность. Менеджер кэша следит за соответствием открытых файлов и файлов, отображаемых в память (с помощью функции MapViewOfFile ). Каждый раз, когда процесс считывает файл или отображает его в память, этот запрос удовлетворяется из кэша путем копирования соответствующего блока в
Аккуратная реализация кэширования требует решения нескольких проблем.
Во-первых, емкость буфера кэша ограничена. У системного кэша нет собственного рабочего набора - он входит в единый системный рабочий набор. Размером системного рабочего набора управляет менеджер памяти, отвечающий за его расширение или усечение. При этом величина, помеченная как размер системного кэша на панели диспетчера задач, относится к размеру всего системного рабочего набора.
Во-вторых, поскольку кэширование использует механизм отложенной записи (
Записываемые данные в течение некоторого времени накапливаются, после чего сбрасываются на диск пакетом. С точки зрения быстродействия и снижения риска от возможных потерь очень важен выбор частоты сброса кэша. Обычно подсистема отложенной записи раз в секунду сбрасывает на диск одну восьмую количества модифицированных страниц системного кэша.
ОС Windows позволяет организовать вариант синхронного режима работы с отдельными файлами, задаваемый при открытии файла, при котором все изменения в файле немедленно сохраняются на диске. Для этого можно, например, установить флаг FILE_FLAG_WRITE_THROUGH при вызове функции CreateFile. Фактически, это отказ от кэширования и, соответственно, резкое снижение производительности.
Кроме того в любой момент можно принудительно сбросить содержимое кэша открытого файла на диск с помощью функции FlushFileBuffers. Напомним, что для отображаемого файла имеется аналогичная функция FlushViewOfFile.
#include <windows.h>
#include <stdio.h>
void main(void) {
HANDLE hFile, hHeap;
int iRet = 0;
void *pMem;
long FileSize = 0, FilePos = 0;
DWORD iRead = 0, iWrite = 0;
char * String;
hFile = CreateFile("MYFILE.TXT", GENERIC_READ| GENERIC_WRITE,0,
NULL, OPEN_EXISTING,FILE_ATTRIBUTE_NORMAL |0, NULL);
if (hFile == INVALID_HANDLE_VALUE) printf("Could not open file \n");
FileSize = GetFileSize(hFile, NULL);
printf("FileSize = %d\n",FileSize);
hHeap = GetProcessHeap();
pMem = HeapAlloc(hHeap, HEAP_ZERO_MEMORY, FileSize + 2);
String = (char *)pMem;
ReadFile(hFile, pMem, FileSize, iRead, NULL);
printf("Read %d bytes \n", iRead);
for(FilePos = 0; FilePos < FileSize; FilePos++)
String[FilePos] = '1';
SetFilePointer(hFile, 0, NULL, FILE_BEGIN);
getchar();
WriteFile(hFile, pMem, FileSize, iWrite, NULL);
printf("Write %d bytes \n", iWrite);
iRet = FlushFileBuffers(hFile);
if(iRet == 0) printf("FlushFileBuffer Error\n");
HeapFree(hHeap, 0, pMem);
CloseHandle(hFile);
}
Приведенная программа считывает большой файл (рекомендуемый размер - несколько мегабайт) в буфер памяти. Затем она меняет содержимое буфера и записывает его на диск. При этом программа пытается сбросить содержимое кэша с помощью функции FlushFileBuffers.
За результатами работы программы можно наблюдать с помощью счетчика "сбросов данных" кэша. Счетчик ведет себя в соответствии с рисунком, где максимальный пик появляется вслед за нажатием клавиши "Enter".
(рис 12.10) Поведение счетчика "сбросов данных" кэшаРекомендуется модифицировать данную программу и проанализировать поведение системы отложенного сброса кэша при помощи соответствующих счетчиков производительности.
Кэширование - не единственный способ увеличения производительности системы. Другая важная техника - сокращение количества движений считывающей головки диска за счет разумной
Поскольку разрушение файловой системы зачастую более опасно, чем разрушение компьютера, файловые системы должны разрабатываться с учетом подобной возможности. Сохранность информации может быть обеспечена за счет ее избыточности (резервное копирование, зеркалирование, образование RAID массивов). Файловые системы современных ОС содержат специальные средства для поддержки собственной целостности и непротиворечивости.
Как правило, файловая операция затрагивает сразу несколько объектов файловой системы. Например, запись в файл предполагает выделение ему блоков диска, модификацию
Для обозначения совокупности действий, выполняемых файловой операцией, используется термин транзакция. Очевидно, что для сохранения целостности файловой системы транзакция должна выполняться целиком или не выполняться вообще.
Одним из средств поддержки целостности является журналирование. Последовательность действий с объектами во время транзакции протоколируется, и, если произошел останов системы, то, имея в наличии протокол, можно осуществить откат системы назад в исходное целостное состояние, в котором она пребывала до начала транзакции.
В журнал заносятся не все изменения, а лишь изменения метаданных (
Для файла-журнала отводится вторая запись таблицы
Применяемая схема - это результат компромисса между полной отказоустойчивостью системы и максимальной производительностью файловых операций. Разумеется, в распоряжении пользователя остаются средства организации сквозной записи на диск и принудительного сброса на диск кэша NTFS ( FlushFileBuffer ).
Если нарушение целостности файловой системы все же произошло, то можно прибегнуть к помощи специализированных утилит (chkdsk, scandisk и др.). Они могут запускаться после загрузки или после сбоя и осуществляют многократное сканирование разнообразных структур данных файловой системы в поисках противоречий.
Наличие дефектных блоков на диске - обычное дело. Под "плохими" блоками обычно понимают блоки диска, для которых вычисленная контрольная сумма считываемых данных не совпадает с хранимой контрольной суммой. В NTFS применяется один из способов нейтрализации данной проблемы - конструирование файла, содержащего дефектные блоки. Для этого файла зарезервирована запись 8 в таблице
Для решения ряда проблем необходимо уметь фиксировать изменения файловой системы по истечении некоторого промежутка времени. Например, обнаружение нарушения целостности файлов, содержащих компоненты самой операционной системы, является способом защиты от внешнего навязывания и одним из средств повышения общей безопасности системы (см. лекцию 15 ). Другим примером может быть актуализация сведений о файлах в диалогах и окнах программ, работающих с файлами.
Для решения подобных задач ОС Windows располагает самыми широкими возможностями. Для знакомства с данной техникой рекомендуется изучить работу программных примеров из MSDN (см. раздел MSDN Using File I/O), или особенности применения функции FindFirstChangeNotification.
Подобно многим современным операционным системам ОС Windows поддерживает несколько файловых систем (
Код, реализующий функциональность каждой файловой подсистемы ОС, входит в состав соответствующего драйвера файловой системы. Запрос прикладной программы на чтение (запись) из файла передается диспетчеру ввода-вывода, который пытается обслужить этот запрос с помощью единого интегрированного кэша (см. рис 12.8).
Если нужная информация в кэше отсутствует, диспетчер ввода-вывода обращается к устройству, содержащему данный файл, подбирая драйвер, соответствующий данному устройству. Драйвер конкретной файловой системы по имени файла и байтовому смещению определяет номер блока на диске и переадресует запрос на обработку этого блока драйверу диска.
Помимо кэша драйверы файловых систем тесно интегрированы с диспетчером памяти, что позволяет обеспечить корректность и когерентность механизма проецирования файлов в память.
Настоящая лекция описывает отдельные аспекты реализации файловой системы NTFS. Главная функция файловой системы - связь символьного имени с блоками диска - реализована за счет поддержки списка блоков в записи о файле в главной файловой таблице
Для получения официальных документов о завершении программы дополнительного профессионального образования (удостоверения о повышении квалификации, дипломов о профессиональной переподготовке и MBA) необходимо предоставить:
Внимание! Вы можете не заказывать доставку бумажной версии официального документы, а скачать его в электронном виде и распечатать самостоятельно. Информация о выданном документе в течение 1 месяца загружается в Федеральную информационную систему «Федеральный реестр сведений о документах об образовании и (или) о квалификации, документах об обучении» - ФИС ФРДО.
Доступ на новый сайт осуществляется с использованием адреса электронной почты, который был указан вами при регистрации на "старом". Мы постарались перенести все ваши данные с прежнего ресурса, однако не исключена вероятность потери части информации.
При возникновении проблемы со входом, воспользуйтесь функцией сброса пароля
Если вы обнаружите несоответствия, пожалуйста, сообщите нам.