"3.Внутреннее устройство Windows (гл. 8-11)" - читать интересную книгу автора (Руссинович Марк, Соломон Дэвид)ГЛABA 11 Диспетчер кэшаДиспетчер кэша (cache manager) — это набор функций режима ядра и системных потоков, во взаимодействии с диспетчером памяти обеспечивающих кэширование данных для всех драйверов файловых систем Windows (как локальных, так и сетевых). B этой главе мы поясним, как работает диспетчер кэша, что представляют собой его внутренние структуры данных и функции, как определяется размер кэшей при инициализации системы, как он взаимодействует с другими компонентами операционной системы и каким образом можно наблюдать за его активностью с помощью счетчиков производительности. Мы также рассмотрим пять флагов Windows-функции Диспетчер кэша: • поддерживает все файловые системы Windows (как локальные, так и сетевые), исключая необходимость реализации в каждой файловой системе собственного кода управления кэшем; • c помощью диспетчера памяти контролирует, какие части и каких файлов находятся в физической памяти (обеспечивая компромисс между потребностями в физической памяти пользовательских процессов и операционной системы); • в отличие от большинства других систем кэширования, которые кэшируют данные на основе логических блоков (смещений внутри дисковых томов), кэширует данные на основе виртуальных блоков (смещений внутри файлов), что позволяет реализовать алгоритм интеллектуального опережающего чтения и обеспечить высокоскоростной доступ к кэшу без участия драйверов файловых систем (этот метод кэширования называется быстрым вводом-выводом); • распознает параметры, передаваемые приложениями при открытии файлов (например, прямой или последовательный доступ, временный файл или постоянный и т. д.); • поддерживает восстанавливаемые файловые системы (например, регистрирующие транзакции), что дает возможность восстанавливать данные после аварий. Основное внимание мы уделяем тому, как эта функциональность используется в диспетчере кэша, но в данном разделе мы обсудим концепции, лежащие в ее основе. B некоторых операционных системах данные кэшируются каждой файловой системой индивидуально. Это приводит к дублированию кода, отвечающего за кэширование и управление памятью, или к ограничению видов данных, которые можно кэшировать. B противоположность этому подходу Windows предлагает централизованный механизм кэширования всех данных, хранящихся во внешней памяти — на локальных жестких и гибких дисках, сетевых файл-серверах или CD-ROM. Кэшировать можно любые данные — как пользовательские (содержимое файлов при операциях чтения или записи), так и метаданные файловой системы (например, заголовки каталогов и файлов). Как вы еще узнаете из этой главы, метод обращения к кэшу, применяемый Windows, определяется типом кэшируемых данных. Одно весьма необычное свойство диспетчера кэша заключается в том, что он никогда не знает, какая часть кэшируемых данных действительно находится в физической памяти. Вероятно, это звучит несколько странно, поскольку кэш предназначен для ускорения ввода-вывода за счет хранения в физической памяти подмножества данных, к которым часто обращаются приложения и система. Все дело в том, что диспетчер кэша обращается к данным, проецируя представления файлов на виртуальные адресные пространства с помощью стандартных объектов «раздел» (в терминах Windows API — объектов «проекция файла»; см. главу 7). По мере доступа к адресам проецируемых представлений файлов диспетчер памяти подгружает нерезидентные блоки в физическую память. A при необходимости диспетчер памяти может выгружать данные из кэша обратно в файлы, проецируемые на кэш. Используя кэширование на основе проецирования файлов на виртуальное адресное пространство, диспетчер кэша избегает генерации пакетов запроса ввода-вывода (IRP) при обращении к данным кэшируемых файлов. Вместо этого он просто копирует данные по виртуальным адресам, по которым проецируются кэшируемые данные, а диспетчер памяти при необходимости подгружает данные в память (или выгружает их из нее). Этот процесс позволяет диспетчеру памяти подбирать глобальный баланс между объемом памяти, выделенной системному кэшу, и объемом памяти, нужной пользовательским процессам. (Диспетчер кэша также инициирует ввод-вывод, например отложенную запись, но сама запись страниц осуществляется диспетчером памяти.) Как вы узнаете из следующего раздела, такая архитектура дает возможность процессам, открывающим кэшируемые файлы, видеть те же данные, что и процессам, проецирующим эти файлы на свои адресные пространства. Одна из важных функций диспетчера кэша — гарантировать любому процессу, обращающемуся к кэшируемым данным, получение самой последней версии этих данных. Ситуация, при которой один процесс открывает файл (и, следовательно, делает его кэшируемым), тогда как другой напрямую проецирует этот файл на свое адресное пространство (через Windows-фyнкцию Поэтому, если, например, на пользовательское адресное пространство процесса 1 проецируется представление 1 файла и процесс 2 обращается к тому же представлению через системный кэш, то процесс 2 будет видеть любые изменения в этом представлении по мере их внесения процессом 1, а не после сброса измененных данных из кэша на диск. Диспетчер памяти сбрасывает не все страницы, проецируемые на пользовательские пространства, а лишь те, о которых он знает, что они изменены (установлен бит изменения). По этому любой процесс, обращающийся к файлу, всегда видит его самую последнюю версию, даже если одни процессы открыли этот файл через подсистему ввода-вывода, а другие проецируют его на свои адресные пространства с помощью соответствующих Windows-функций. Диспетчеры кэша многих операционных систем (включая Novell NetWare, OpenVMS и ранние версии UNIX) кэшируют данные на основе • Появляется возможность реализации интеллектуального опережающего чтения (intellegent read-ahead), так как диспетчер кэша следит за тем, части каких файлов находятся в кэше, и это позволяет ему предсказывать, к какой следующей порции данных обратится вызывающая программа. • Подсистема ввода-вывода может запрашивать данные, уже находящиеся в кэше, в обход файловой системы (быстрый ввод-вывод). Поскольку диспетчеру кэша известно, какие части и каких файлов находятся в кэше, он может вернуть адрес кэшируемых данных для выполнения запроса на ввод-вывод без обращения к файловой системе. Подробнее об интеллектуальном опережающем чтении и быстром вводе-выводе мы расскажем чуть позже. B диспетчер кэша заложена поддержка не только кэширования файлов, но и Восстанавливаемые файловые системы вроде NTFS способны реконструировать структуру дискового тома после аварии системы. Это означает, что операции ввода-вывода, еще выполнявшиеся на момент аварии, должны быть либо доведены до конца, либо корректно отменены после перезагрузки системы. Частично выполненные операции ввода-вывода могут повредить дисковый том и даже сделать его недоступным. Bo избежание такой проблемы восстанавливаемая файловая система ведет файл журнала, в котором регистрирует каждое предполагаемое обновление структуры файловой системы (метаданные файловой системы) — еще до того, как оно будет выполнено. Если сбой происходит во время изменения данных тома, восстанавливаемая файловая система использует информацию из файла журнала и выполняет нужные операции. Чтобы обеспечить успешное восстановление тома, каждый элемент (запись) файла журнала, документирующий изменения в данных тома, должен быть записан на диск до самого обновления данных. Поскольку запись на диск кэшируется, файловая система должна взаимодействовать с диспетчером кэша, чтобы гарантировать выполнение следующей последовательности операций. 1. Файловая система заносит в файл журнала запись, документирующую изменение данных тома, которое она собирается выполнить. 2. Файловая система вызывает диспетчер кэша для сброса на диск записи файла журнала. 3. Файловая система записывает в кэш обновленные данные тома, т. е. модифицирует свои кэшируемые метаданные. 4. Диспетчер кэша сбрасывает модифицированные метаданные на диск, обновляя структуру тома. (Ha самом деле записи файла журнала, как и модифицированные метаданные, сбрасываются на диск пакетами.) Записывая данные в кэш, файловая система предоставляет Когда диспетчер кэша готов сбросить на диск группу измененных страниц, он определяет наибольший LSN, сопоставленный со сбрасываемыми на диск страницами, и сообщает его файловой системе. Далее файловая система может ответно вызвать диспетчер кэша и заставить его сбросить данные файла журнала вплоть до точки, представленной указанным LSN. Сбросив данные файла журнала вплоть до указанного LSN, диспетчер кэша сбрасывает на диск и соответствующие обновления в структуре тома, что гарантирует регистрацию предстоящих операций до их выполнения. Таким образом и достигается возможность восстановления дискового тома после аварии системы. Поскольку диспетчер кэша Windows кэширует файлы на основе виртуальных блоков, ему передается регион в системной части виртуальных адресных пространств (а не область физической памяти). Диспетчер кэша разбивает такой регион на 256-килобайтные слоты, называемые также представлениями (рис. 11-2). (Подробнее о структуре системного пространства см. главу 7.) При первой операции ввода-вывода (чтения или записи) над файлом диспетчер кэша проецирует на свободный слот адресного пространства системного кэша 256-килобайтное представление области файла, выровненной по границе 256 Кб и содержащей запрошенные данные. Например, если из файла считывается 10 байтов по смещению 300 000 байтов от его начала, то проецируемое представление будет начинаться со смещения 262 144 (вторая область файла, выровненная по границе 256 Кб) и займет 256 Кб. Диспетчер кэша проецирует представления файлов на слоты адресного пространства кэша по принципу карусели: первое запрошенное представление — на первый 256-килобайтный слот, второе — на второй и т. д. рис. 11-3). B этом примере первым был спроецирован файл В, вторым — А, третьим — С, поэтому проецируемая часть файла B занимает первый слот кэша. Заметьте, что спроецирована лишь первая 256-килобайтная часть файла В, так как обращение было лишь к части файла и так как файл С, размер которого составляет всего 100 Кб, требует выделения своего 256-килобайтного слота кэша. Рис. 11 -3. Файлы различного размера, спроецированные в системный кэш Диспетчер кэша гарантирует, что представление проецируется на то время, пока оно активно (хотя представления могут оставаться спроецированными после того, как становятся неактивными). Однако представление помечается как активное, только когда выполняется операция чтения или записи над соответствующим файлом. Если процесс, открывающий файл вызовом Страницы, соответствующие представлениям файлов, открытых с флагом FILE_FLAG_SEQUENTIAL_SCAN, перемещаются в начало списков, а все остальные — в конец. Такая схема способствует повторному использованию страниц, которые принадлежат файлам, открытым для последовательного чтения, и заставляет использовать малые объемы физической памяти при копировании больших файлов. Если диспетчеру кэша требуется спроецировать представление файла, а свободных слотов в кэше нет, он отключает неактивное представление, спроецированное последним, и использует освободившийся слот. B отсутствие таких представлений возвращается ошибка ввода-вывода с сообщением о том, что системных ресурсов для выполнения данной операции недостаточно. Эта ситуация крайне маловероятна, так как возникает только при одновременном доступе к тысячам файлов. B следующих разделах мы объясним, как Windows вычисляет размер системного кэша. Как и в большинстве других вычислений, связанных с управлением памятью, размер системного кэша определяется несколькими факторами, в том числе объемом памяти и конкретным выпуском Windows. Как вы увидите в дальнейшем, параметр LargeSystemCache в разделе реестра HKLM\SYSTEM\CurrentControlSet\Control\Session Manager\Memory Management влияет как на виртуальный размер кэша, так и на физический. По умолчанию в Windows 2000 Professional и Windows XP это значение равно 0, а в системах Windows Server — 1. B Windows 2000 Server данное значение можно регулировать через GUI, изменяя свойства службы файлового сервера; для этого надо открыть окно свойств сетевого соединения и выбрать File And Printer Sharing For Microsoft Networks (Служба доступа к файлам и принтерам сетей Microsoft). Эта служба имеется и в Windows 2000 Professional, но там ее параметры настраивать нельзя. Ha рис. 11 -4 показано диалоговое окно, через которое в Windows 2000 Server можно изменить объем памяти, выделяемой для локальных и сетевых приложений сетевой службой сервера. B Windows 2000 Server с установленными Terminal Services (Службы терминала) переключатель Maximize Data Throughput For File Sharing (Макс, пропускная способность доступа к общим файлам), показанный на рис. 11-4, активен по умолчанию, т. е. параметр LargeSystemCache равен 1. При выборе любого другого переключателя параметр LargeSystemCache становится равным 0. Каждый из переключателей диалогового окна File And Printer Sharing For Microsoft Networks Properties влияет не только на поведение системного кэша, но и на службу файлового сервера. Рис. 11 -4. Диалоговое окно FiIe and Printer Sharing for Microsoft Networks Properties, позволяющее изменять свойства сетевой службы сервера B Windows XP и Windows Server 2003 модифицировать параметр LargeSystemCache можно через диалоговое окно Performance Options (Параметры быстродействия), которое открывается щелчком кнопки Settings (Параметры) в разделе Performance (Быстродействие) на вкладке Advanced (Дополнительно) апплета System (Система) из Control Panel (Панель управления). B этом диалоговом окне перейдите на очередную вкладку Advanced (Дополнительно). Если в разделе Memory Usage (Использование памяти) вы выбираете System Cache (системного кэша), параметру LargeSystemCache присваивается значение 1, а если вы выбираете Programs (программ) — 0 (рис. 11-5). Рис. 11 -5. Виртуальный размер системного кэша является функцией объема установленной физической памяти. По умолчанию это значение равно 64 Мб. Если в системе более 4032 страниц (16 Мб) физической памяти, виртуальный размер кэша устанавливается равным 128 Мб плюс 64 Мб на каждые дополнительные 4 Мб физической памяти. Используя этот алгоритм, можно подсчитать виртуальный размер системного кэша на компьютере, например, с 64 Мб физической памяти: Минимальный и максимальный виртуальные размеры системного кэша на разных платформах, а также его стартовый и конечный адреса показаны в таблице 11 -1. Если на платформе x86 рассчитанный системой виртуальный размер кэша превышает 512 Мб, он ограничивается 512 Мб; однако при параметре LargeSystemCache, равном 1, в той же ситуации кэшу назначается до 960 Мб виртуальной памяти из дополнительного диапазона адресов, называемого B таблице 11-2 перечислены системные переменные, которые содержат виртуальный размер и адрес системного кэша. ЭКСПЕРИМЕНТ: просмотр виртуального размера кэша Виртуальный размер кэша не показывается каким-либо счетчиком производительности, так что единственный способ узнать его значение — получить содержимое переменной ядра B этом примере использована х86-система под управлением Windows XP с параметром LargeSystemCache, равным 0; как видите, виртуальный размер кэша в такой системе составляет 0x20000 страниц. Поскольку на платформе x86 размер страниц равен 4 Кб, под виртуальный кэш выделено 512 Мб из 2-гигабайтного системного адресного пространства. Как уже упоминалось, одно из ключевых отличий архитектуры диспетчера кэша Windows от таковой в других операционных системах — делегирование управления физической памятью диспетчеру памяти. Ввиду этого размером кэша управляет уже имеющийся в операционной системе код, отвечающий за обработку расширения и усечения рабочего набора, а также за управление списками модифицированных и простаивающих страниц. У системного кэша нет собственного рабочего набора — он использует единый системный набор, в который входят кэш данных, пул подкачиваемой памяти, а также подкачиваемый код Ntoskrnl и драйверов. Как упоминалось в главе 7, этот рабочий набор имеет внутреннее название Выяснить физический размер системного кэша, сравнить его с суммарным физическим размером системного рабочего набора, а также получить информацию об ошибках страниц для системного рабочего набора позволяют счетчики производительности или системные переменные, перечисленные в таблице 11-3. ЭКСПЕРИМЕНТ: просмотр рабочего набора кэша Как показано на листинге ниже, команда Хотя системный рабочий набор включает объем физической памяти, проецируемой на представления в виртуальном адресном пространстве кэша, он не обязательно отражает общий объем файловых данных, кэшируемых в физической памяти. Между этими двумя значениями нередко бывают расхождения, потому что часть файловых данных может находиться в принадлежащем диспетчеру памяти списке простаивающих или модифицированных страниц. Вспомните из главы 7, что при усечении рабочего набора или замене страниц диспетчер памяти может переместить измененные страницы из рабочего набора в список простаивающих или модифицированных страниц — в зависимости от того, куда должны быть записаны данные, содержащиеся на такой странице, перед ее повторным использованием — в страничный файл или в какой-то другой. Если бы у диспетчера памяти не было таких списков, то всякий раз, когда какой-нибудь процесс обращался бы к данным, ранее удаленным из его рабочего набора, диспетчеру памяти приходилось бы считывать их с диска. A так диспетчер памяти может просто вернуть нужную страницу в рабочий набор процесса (если она, конечно, присутствует в одном из этих списков). To есть списки служат кэшами данных из страничного файла, исполняемых образов или файлов данных. Значит, общий объем файловых данных, кэшируемых в системе, складывается не только из размера системного рабочего набора, но и из размеров списков простаивающих и модифицированных страниц. Вот пример, иллюстрирующий, как диспетчер кэша способен привести к кэшированию в физической памяти гораздо большего объема файловых данных, чем может содержаться в системном рабочем наборе. Рассмотрим систему, выступающую в роли выделенного файл-сервера. B этой системе имеется 8 Гб физической памяти, и виртуальный размер кэша составляет 960 Мб (максимальный размер в х86-системах). Таким образом, предельный размер файловых данных, которые можно напрямую спроецировать в виртуальную память кэша, составляет 960 Мб. Клиентское приложение обращается к файловым данным на сервере через сеть. Драйвер файл-сервера (\Windows\System32\Drivers\Srv.sys) (см. главу 12) использует интерфейсы диспетчера кэша для чтения и записи файловых данных в интересах клиента. Если клиенты считывают несколько тысяч файлов, каждый размером по 1 Мб, диспетчеру кэша придется повторно использовать представления при проецировании 961-го файла. При последующих операциях чтения он будет отменять проецирование представлений для старых файлов и заново проецировать их для новых. Когда диспетчер кэша отменяет проецирование какого-либо представления, диспетчер памяти не отбрасывает файловые данные в рабочем наборе кэша, соответствующие этому представлению, а перемещает их в список простаивающих страниц. B отсутствие запросов на выделение физической памяти под любые другие задачи список простаивающих страниц может занимать почти всю физическую память за вычетом системного рабочего набора. Иначе говоря, практически все 8 Гб физической памяти сервера будут задействованы для кэширования файловых данных, как показано на рис. 11-6. Рис. 11 -6. Пример использования почти всей физической памяти под файловый кэш Поскольку общий объем кэшируемых файловых данных складывается из размеров системного рабочего набора, списка модифицированных страниц и списка простаивающих страниц, а эти размеры контролируются диспетчером памяти, в каком-то смысле его можно назвать истинным диспетчером кэша. Подсистема диспетчера кэша просто предоставляет удобные интерфейсы для доступа к файловым данным через диспетчер памяти и определяет политики опережающего чтения (read-ahead) и отложенной записи (write-behind), которые влияют на то, какие данные диспетчер памяти будет удерживать в физической памяти. Для более точного отображения полного объема файловых данных, кэшируемых в системе, диспетчер задач и Process Explorer предоставляют параметр System Cache (Системный кэш), отражающий суммарный размер системного рабочего набора и списков простаивающих и модифицированных страниц. Пример для Process Explorer представлен на рис. 11-7. Для отслеживания кэшируемых файлов диспетчер кэша использует следующие структуры данных. • Каждый 256-килобайтный слот системного кэша описывается VACB. • У каждого отдельно открытого кэшируемого файла есть закрытая карта кэша с информацией, применяемой для контроля опережающего чтения. • Каждый кэшируемый файл имеет общую структуру карты кэша, которая указывает на слоты системного кэша, содержащие проецируемые представления файла. Эти структуры и их взаимосвязи описываются в следующих разделах. Диспетчер кэша отслеживает состояние спроецированных на системный кэш представлений с помощью массива структур данных, называемых Как видно на рис. 11-9, в первом поле VACB содержится виртуальный адрес данных системного кэша. Второе поле является указателем на общую (совместно используемую) структуру карты кэша, которая идентифицирует кэшируемый файл. Третье поле определяет смещение начала представления (внутри файла). Наконец, VACB содержит счетчик ссылок на представление, т. е. число активных операций чтения или записи над данным представлением. При выполнении операции ввода-вывода над файлом счетчик ссылок VACB увеличивается на 1, а по окончании такой операции уменьшается на 1. Когда счетчик ссылок не равен 0, VACB считается активным. B случае обращения к метаданным файловой системы счетчик активных операций отражает число драйверов файловых систем, которые владеют заблокированными в памяти страницами данного представления. Каждому открытому описателю файла соответствует объект «файл» (см. главу 9). Если файл кэшируется, его объект «файл» указывает на У каждого кэшируемого файла (в противоположность объекту «файл») есть структура При запросе на чтение данных из какого-либо файла диспетчер кэша должен ответить на два вопроса. 1. Находится ли файл в кэше? 2. Если да, то какие VACB (если таковые есть) ссылаются на запрошенный адрес? Иначе говоря, диспетчер кэша должен выяснить, проецируется ли представление файла (с нужным смещением) на системный кэш. Если ни один VACB не содержит нужное смещение в файле, запрошенные данные в настоящий момент не проецируются на системный кэш. Для учета представлений данного файла, проецируемых на системный кэш, диспетчер кэша поддерживает массив указателей на VACB — Схема на рис. 11–11 иллюстрирует четыре раздела из трех файлов, проецируемых в данный момент на системный кэш. Когда процесс обращается к файлу по заданному адресу, диспетчер кэша ищет подходящий элемент в массиве индексов VACB для этого файла, чтобы определить, проецируются ли на кэш запрошенные данные. Если элемент массива отличен от 0 (и, следовательно, содержит указатель на VACB), нужная область файла находится в кэше. VACB в свою очередь указывает на адрес, по которому на системный кэш проецируется представление файла. A если элемент массива равен 0, диспетчер кэша должен найти в системном кэше свободный слот (а значит, свободный VACB) для проецирования необходимого представления. Рис. 11–10. Структуры данных кэша, индивидуальные для файлов Для оптимизации своего размера общая карта кэша содержит массив индексов VACB из 4 элементов. Поскольку каждый VACB описывает 256 Кб, элементы этого компактного массива индексов фиксированного размера могут указывать на элементы массива VACB, которые в совокупности способны описывать файл размером до 1 Мб. Если размер файла превышает 1 Мб, из неподкачиваемого пула выделяется память под отдельный массив индексов VACB; его размер определяется делением размера файла на 256 Кб с последующим округлением результата до ближайшего большего целого значения. После этого общая карта кэша указывает на данную структуру. Рис. 11–11. Массивы индексов VACB Если длина файла превышает 32 Мб, то для еще большей оптимизации массив индексов VACB, созданный в пуле неподкачиваемой памяти, становится разреженным многоуровневым массивом индексов (sparse multilevel index array), в котором каждый массив индексов состоит из 128 элементов. Число уровней, необходимых для файла, вычисляется по формуле: Полученное значение надо округлить до ближайшего большего целого. Число 18 в уравнении обусловлено тем, что VACB представляет 256 Кб, а 256 Кб — это 218. Наконец, число 7 присутствует в уравнении потому, что каждый уровень массива состоит из 128 элементов, а 128 — это 27. Следовательно, файл максимальной длины, которая может быть описана как 263 (максимальный размер, поддерживаемый диспетчером кэша), потребует всего 7 уровней. Массив является разреженным, так какдиспетчер кэша создает ветви лишь для активных представлений на самом низком уровне массива индексов. Ha рис. 11–12 показан пример многоуровневого массива VACB для разреженного файла, размер которого требует для описания 3 уровня. Такая схема нужна для эффективной обработки разреженных файлов, которые могут достигать очень больших размеров и в которых лишь малая часть может быть занята действительными данными; поэтому в массиве выделяется ровно столько места, сколько нужно для проецируемых в данный момент представлений файла. Например, разреженный файл размером 32 Гб, у которого только 256 Кб проецируются на виртуальное адресное пространство кэша, потребует массив VACB с тремя массивами индексов, поскольку лишь одна ветвь массива имеет проекцию, а для файла длиной 32 Гб (235 байтов) нужен трехуровневый массив. Если бы диспетчер кэша не оптимизировал многоуровневые массивы VACB, для этого файла пришлось бы создать массив VACB со 128 000 элементов, что эквивалентно 1000 массивам индексов. ЭКСПЕРИМЕНТ: просмотр общей и закрытых карт кэша Команда Первый адрес указывает местонахождение структуры данных области управления (control area), с помощью которой диспетчер памяти отслеживает диапазон адресов. (Более подробные сведения см. в главе 7.) B области управления хранится указатель на объект «файл», coответствующий представлению в кэше. Объект «файл» идентифицирует экземпляр открытого файла — в данном случае справочного файла из Debugging Tools for Windows. Теперь, чтобы увидеть структуру области управления, введите следующую команду с адресом идентифицированного вами элемента в этой области: Потом изучите объект «файл», на который ссылается область управления: При первом обращении к файловым данным для чтения или записи драйвер файловой системы должен определить, проецируются ли нужные части файла на системный кэш. Если нет, драйвер файловой системы должен вызвать функцию Далее драйвер файловой системы вызывает одну из нескольких функций для доступа к данным файла. Существует три основных метода доступа к кэшируемым данным, каждый из которых рассчитан на применение в определенной ситуации: • копирование (copy method) — пользовательские данные копируются между буферами кэша в системном пространстве и буфером процесса в пользовательском пространстве; • проецирование и фиксация (mapping and pinning method) — данные считываются и записываются прямо в буферы кэша по виртуальным адресам; • обращение к физической памяти (phisycal memory access method) — данные считываются и записываются прямо в буферы кэша по физическим адресам. Чтобы избежать бесконечного цикла при обработке диспетчером памяти ошибки страницы, драйверы файловых систем должны поддерживать два варианта чтения файлов — с кэшированием и без. B таких случаях диспетчер памяти вызывает файловую систему для получения данных из файла (через драйвер устройства) и запрашивает операцию чтения без кэширования, устанавливая в IRP флаг «no cache». Рис. 11–13 иллюстрирует типичное взаимодействие между диспетчером кэша, диспетчером памяти и драйверами файловой системы в ответ на пользовательские операции файлового ввода-вывода (чтения или записи). Диспетчер кэша вызывается файловой системой через интерфейсы копирования (функции Рис. 11–13. Взаимодействие файловой системы с диспетчерами кэша и памяти B следующих трех разделах мы рассмотрим все три ранее упомянутых механизма доступа к кэшу, их предназначение и принципы использования. Поскольку системный кэш находится в системном пространстве, он проецируется на адресное пространство каждого процесса. Однако, как и любые другие страницы системного пространства, страницы кэша недоступны в пользовательском режиме, поскольку иначе в защите появилась бы потенциальная дыра. (Например, процесс, не имеющий соответствующих прав, мог бы считать данные из файла, который находится в какой-либо части системного кэша.) Таким образом, операции чтения и записи пользовательских приложений в файлы должны обслуживаться процедурами режима ядра, которые копируют данные между буферами кэша в системном пространстве и буферами приложения, расположенными в адресном пространстве процесса. Функции, которые драйверы файловой системы могут использовать для выполнения этих операций, перечислены в таблице 11 -4. Активность операций чтения из кэша можно увидеть через счетчики производительности и системные переменные, представленные в таблице 11-5. По мере чтения и записи данных в дисковые файлы пользовательскими приложениями драйверы файловых систем должны считывать и записывать данные, описывающие сами файлы (метаданные, или данные о структуре тома). Так как драйверы файловых систем выполняются в режиме ядра, они могут модифицировать данные непосредственно в системном кэше при условии уведомления об этом диспетчера кэша. Для поддержки такой оптимизации диспетчер кэша предоставляет функции, перечисленные в таблице 11-6. Эти функции позволяют драйверам файловых систем находить в виртуальной памяти нужные метаданные и напрямую модифицировать их без использования промежуточных буферов. Если драйверу файловой системы нужно считать метаданные из кэша, он вызывает интерфейс диспетчера кэша, отвечающий за проецирование, чтобы получить виртуальный адрес требуемых данных. Диспетчер кэша подгружает в память все запрошенные страницы и возвращает управление драйверу файловой системы. После этого драйвер может напрямую обращаться к данным. Если драйверу файловой системы необходимо модифицировать страницы кэша, он вызывает сервисы диспетчера кэша, отвечающие за фиксацию модифицируемых страниц в памяти. Ha самом деле эти страницы не блокируются в памяти (как это происходит в тех случаях, когда драйвер устройства блокирует страницы для передачи данных с использованием прямого доступа к памяти). По большей части драйвер файловой системы помечает их поток метаданных как «no write», сообщая подсистеме записи модифицированных страниц диспетчера памяти (см. главу 7) не сбрасывать страницы на диск до тех пор, пока не будет явно указано иное. После отмены фиксации страниц диспетчер кэша сбрасывает на диск все измененные страницы и освобождает представление кэша, которое было занято метаданными. Интерфейсы проецирования и фиксации решают одну сложную проблему реализации файловых систем — управление буферами. B отсутствие возможности прямых операций над кэшированными метаданными файловая система была бы вынуждена предугадывать максимальное число буферов, которое понадобится ей для обновления структуры тома. Обеспечивая файловой системе прямой доступ к ее метаданным и их изменение непосредственно в кэше, диспетчер кэша устраняет потребность в буферах и просто обновляет структуру тома в виртуальной памяти, предоставленной диспетчером памяти. Единственным ограничением файловой системы в этом случае является объем доступной памяти. Вы можете наблюдать за интенсивностью операций, связанных с фиксацией и проецированием в кэше, с помощью счетчиков производительности и системных переменных, перечисленных в таблице 11-7. B дополнение к интерфейсам проецирования и фиксации, используемым при прямом обращении к кэшированным метаданным, диспетчер кэша предоставляет третий интерфейс — Интерфейс DMA возвращает файловой системе физические адреса кэшируемых пользовательских данных (а не виртуальные, которые возвращаются интерфейсами проецирования и фиксации), и эти адреса могут быть использованы для прямой передачи данных из физической памяти на сетевое устройство. Хотя при передаче небольших порций данных (1–2 Кб) можно пользоваться обычными интерфейсами копирования на основе буферов, при передаче больших объемов данных интерфейс DMA значительно повышает быстродействие сетевого сервера, обрабатывающего файловые запросы от удаленных систем. Для описания ссылок на физическую память служит список дескрипторов памяти (memory descriptor list, MDL) (см. главу 7). DMA-интерфейс диспетчера кэша состоит их четырех функций (таблица 11-8). Вы можете исследовать активность, связанную с MDL-чтением из кэша, через счетчики производительности или системные переменные, перечисленные в таблице 11-9. Операции чтения и записи, выполняемые над кэшируемыми файлами, по возможности обрабатываются с применением высокоскоростного механизма — Поскольку диспетчер кэша в архитектуре системы размещается поверх подсистемы виртуальной памяти, драйверы файловых систем могут использовать этот диспетчер для доступа к данным путем простого копирования их в страницы (или из страниц), проецируемые на тот файл, на который ссылается пользовательская программа, без генерации IRR. Быстрый ввод-вывод возможен не всегда. Например, первая операция чтения или записи требует подготовки файла к кэшированию (его проецирования на кэш и создания структур данных кэша, описанных в разделе «Структуры данных кэша» ранее в этой главе). Быстрый ввод-вывод не применяется и в том случае, если вызывающий поток указывает асинхронное чтение или запись, поскольку этот поток может быть приостановлен в ходе операций ввода-вывода, связанных с подкачкой и необходимых для копирования буферов в системный кэш (и из него), и фактически синхронного выполнения запрошенной операции асинхронного ввода-вывода. Однако даже при синхронном вводе-выводе драйвер файловой системы может решить, что обработка запрошенной операции по механизму быстрого ввода-вывода недопустима, если, например, в нужном файле заблокирован какой-то диапазон байтов (в результате вызова Windows-функции Обслуживание чтения или записи с использованием быстрого ввода-вывода включает следующие операции. 1. Поток выполняет операцию чтения или записи. 2. Если файл кэшируется и указан синхронный ввод-вывод, запрос передается входной точке быстрого ввода-вывода драйвера файловой системы. Если файл не кэшируется, драйвер файловой системы готовит файл к кэшированию, чтобы выполнить следующий запрос на чтение или запись за счет быстрого ввода-вывода. 3. Если процедура драйвера файловой системы, отвечающая за быстрый ввод-вывод, определяет, что быстрый ввод-вывод возможен, она вызывает процедуру чтения или записи диспетчера кэша для прямого доступа к данным кэша. (Если быстрый ввод-вывод невозможен, драйвер файловой системы возвращает управление подсистеме ввода-вывода, которая затем генерирует IRP и в конечном счете вызывает в файловой системе обычную процедуру чтения.) 4. Диспетчер кэша транслирует переданное смещение в файле в виртуальный адрес данных в кэше. 5. При операциях чтения диспетчер кэша копирует данные из кэша в буфер процесса, а при операциях записи — из буфера процесса в кэш. 6. Выполняется одна из следующих операций: • при операциях чтения из файла, при открытии которого не был установлен флаг FILE_FLAG_RANDOM_ACCESS, в закрытой карте кэша вызывающего потока обновляется информация, необходимая для опережающего чтения; • при операциях записи устанавливается бит изменения у всех модифицированных страниц кэша, чтобы подсистема отложенной записи сбросила эти страницы на диск; • для файлов, требующих сквозной записи, все измененные данные немедленно сбрасываются на диск. Счетчики производительности и системные переменные, перечисленные в таблице 11–10, позволяют наблюдать за операциями быстрого ввода-вывода в системе. Здесь вы увидите, как диспетчер кэша реализует чтение и запись файловых данных в интересах драйверов файловых систем. Учтите, что диспетчер кэша участвует в файловом вводе-выводе только при открытии файла без флага FILE_FLAG_NO_BUFFERING и последующем чтении или записи через Windows-функции ввода-вывода (например, функции Для реализации Считывание следующего блока файла, к которому происходит последовательное обращение, дает очевидные преимущества. Чтобы распространить эти преимущества и на случаи произвольного (прямого) доступа к данным (в направлении вперед или назад), диспетчер кэша запоминает последние два запроса на чтение в закрытой карте кэша, сопоставленной с описателем файла, к которому обращается программа. Этот метод называется Чтобы еще больше повысить эффективность опережающего чтения, Windows-функция B этом случае опережающее чтение выполняется диспетчером кэша асинхронно, так как это делается в контексте отдельного потока, выполняемого параллельно с вызывающим потоком. Когда диспетчер кэша вызывается для выдачи кэшированных данных, он сначала обращается к запрошенной виртуальной странице, чтобы удовлетворить запрос, а затем ставит в очередь системного рабочего потока еще один запрос на ввод-вывод для выборки дополнительной порции данных. Далее рабочий поток выполняется в фоновом режиме и считывает дополнительные данные, упреждая следующий запрос вызывающего потока. Заранее считанные страницы загружаются в память параллельно выполнению пользовательской программы, так что на момент выдачи ее потоком очередного запроса эти данные уже находятся в памяти. B случае приложений, для которых невозможно предсказать схему чтения данных, функция Диспетчер кэша реализует кэш с обратной отложенной записью (write-back cache with lazy write). Это означает, что данные, записываемые в файлы, сначала хранятся в страницах кэша в памяти, а потом записываются на диск. Таким образом, записываемые данные в течение некоторого времени накапливаются, после чего сбрасываются на диск пакетом, что уменьшает общее число операций дискового ввода-вывода. Для сброса страниц кэша диспетчер кэша должен явно вызвать диспетчер памяти, поскольку в ином случае тот записывает на диск содержимое памяти только при нехватке физической памяти. Ho, если процесс модифицирует кэшируемые данные, пользователь ожидает, что изменения будут своевременно отражены на диске. Выбор частоты сброса кэша очень важен. Если слишком часто сбрасывать кэш, быстродействие системы снизится из-за дополнительного ввода-вывода. A при слишком редком сбросе кэша появится риск потери модифицированных файловых данных в случае аварии системы и нехватки физической памяти (которая будет занята чрезмерно большим количеством модифицированных страниц). Чтобы избежать этих крайностей, раз в секунду в системном рабочем потоке выполняется функция отложенной записи диспетчера кэша, которая сбрасывает на диск (точнее, ставит в очередь на запись) одну восьмую часть измененных страниц системного кэша. Если измененные страницы появляются быстрее, чем сбрасываются, подсистема отложенной записи дополнительно сбрасывает соответствующее дополнительное количество измененных страниц. Реальные операции ввода-вывода выполняются системными рабочими потоками из пула общесистемных критичных рабочих потоков. Наблюдать за активностью подсистемы отложенной записи позволяют счетчики производительности или системные переменные, перечисленные в таблице 11–11. Если вы создаете временный файл вызовом Windows-функции Поскольку некоторые приложения не терпят ни малейших задержек между записью в файл и реальным обновлением данных на диске, диспетчер кэша поддерживает кэширование со сквозной записью (write-through caching), включаемое для каждого объекта «файл» индивидуально; при этом изменения записываются на диск по мере их внесения. Чтобы включить кэширование со сквозной записью, при вызове функции Если подсистема отложенной записи должна записать на диск данные из представления, проецируемого и на адресное пространство другого процесса, ситуация несколько усложняется. Дело в том, что диспетчеру кэша известны лишь страницы, модифицированные им самим. (O страницах, модифицированных другим процессом, знает только этот процесс, так как биты изменения этих страниц находятся в элементах таблиц страниц, принадлежащих исключительно процессу.) Чтобы справиться с этой ситуацией, диспетчер памяти посылает диспетчеру кэша соответствующее уведомление в тот момент, когда пользователь проецирует какой-либо файл. При сбросе такого файла из кэша (например, в результате вызова Windows-функции 1. Пользователь удаляет проекцию представления. 2. Процесс сбрасывает файловые буферы. При ином порядке событий предсказать, какие страницы будут записаны на диск, нельзя. ЭКСПЕРИМЕНТ: наблюдение за операциями сброса кэша Вы можете увидеть, как диспетчер кэша проецирует представления в системный кэш и сбрасывает страницы на диск, запустив оснастку Performance (Производительность) и добавив счетчики Data Maps/sec (Отображений данных/сек) и LazyWrite Flushes/sec (Сбросов ленивой записи/сек), а затем скопировав большой файл из одного места в другое. Ha следующей иллюстрации показаны графики, относящиеся к Data Maps/sec (верхний) и к LazyWrite Flushes/sec (нижний). Файловая система и диспетчер кэша должны определять, повлияет ли запрос кэшированной записи на производительность системы, и исходя из этого планировать отложенные операции записи. Сначала файловая система через функцию Алгоритм расчета порогового числа измененных страниц представлен в таблице 11–13. Результат расчета с использованием этого алгоритма игнорируется, если максимальный размер системного рабочего набора превышает 4 Мб, — а именно так зачастую и происходит. (Определение малого, среднего и большого объема системной памяти см. в главе 7.) Когда максимальный размер рабочего набора превышает 4 Мб, пороговое число измененных страниц устанавливается равным максимальному размеру системного рабочего набора за вычетом 2 Мб. Дросселирование записи также полезно для сетевых редиректоров, передающих данные по медленным коммуникационным каналам. Вообразите, например, локальный процесс, записывающий большой объем данных в удаленную файловую систему по каналу, работающему со скоростью 9600 бод. Данные не попадут на удаленный диск, пока подсистема отложенной записи диспетчера кэша не сбросит кэш на диск. Если редиректор накапливает много измененных страниц, одновременно сбрасываемых на диск, на принимающей стороне может истечь время ожидания данных до окончания их передачи. Развитие событий по такому сценарию можно предотвратить с помощью функции диспетчера кэша ЭКСПЕРИМЕНТ: просмотр параметров дросселирования записи Команда Как видите, число измененных страниц близко к пороговому значению, при котором начинается дросселирование записи Как уже говорилось, диспетчер кэша выполняет отложенную запись и опережающее чтение, передавая запросы в общий пул критичных системных рабочих потоков. Однако в системах с малым и средним объемом памяти он использует на один поток меньше общего количества критичных системных рабочих потоков, а в системах с большим объемом памяти — на два. Внутренне диспетчер кэша организует свои запросы в два списка (которые все равно обслуживаются одним и тем же набором рабочих потоков исполнительной системы): • • Чтобы отслеживать рабочие элементы, направленные рабочим потокам, диспетчер кэша создает собственный ассоциативный список (индивидуальный для каждого процессора и имеющий фиксированную длину) структур рабочих элементов, поставленных в очереди рабочих потоков (ассоциативные списки обсуждаются в главе 7). Число элементов в очереди рабочего потока определяется объемом системной памяти и для систем Windows Professional составляет 32,64 или 128 в системах с малым, средним или большим объемом памяти соответственно (для систем Windows Server с большим объемом памяти — 256). Диспетчер кэша предоставляет быстродействующий интеллектуальный механизм для уменьшения интенсивности дискового ввода-вывода и увеличения общей пропускной способности системы. Осуществляя кэширование на основе виртуальных блоков, диспетчер кэша может выполнять интеллектуальное опережающее чтение. Используя для обращения к файловым данным механизм проецирования файлов, диспетчер кэша предоставляет специальный механизм для быстрого ввода-вывода, который уменьшает нагрузку на процессор при выполнении операций чтения и записи и позволяет возложить все управление физической памятью на диспетчер памяти. A это избавляет от дублирования кода и повышает эффективность работы операционной системы. |
||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
|