ГЛАВА 7 

 Ввод-вывод и файловая система

 

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

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

 

Задачи ОС по управлению файлами и устройствами

 

Подсистема ввода-вывода (Input-Output Subsystem) мультипрограммной ОС при обмене данными с внешними устройствами компьютера должна решать ряд об­щих задач, из которых наиболее важными являются следующие:

□   организация параллельной работа устройств ввода-вывода и процессора;

□   согласование скоростей обмена и кэширование данных;

□   разделение устройств и данных между процессами;

□   обеспечение удобного логического интерфейса между устройствами и осталь­ной частью системы;

□   поддержка широкого спектра драйверов с возможностью простого включения в систему нового драйвера;

□  динамическая загрузка и выгрузка драйверов;

□   поддержка нескольких файловых систем;

□   поддержка синхронных и асинхронных операций ввода-вывода.

В следующих разделах все эти задачи рассматриваются подробно.

 

 

 

 

Организация параллельной работы устройств ввода-вывода и процессора

 

Каждое устройство ввода-вывода вычислительной системы — диск, принтер, тер­минал и т. п. — снабжено специализированным блоком управления, называемым контроллером. Контроллер взаимодействует с драйвером — системным программ­ным модулем, предназначенным для управления данным устройством. Контрол­лер периодически принимает от драйвера выводимую на устройство информацию, а также команды управления, которые говорят о том, что с этой информацией нужно сделать (например, вывести в виде текста в определенную область терми­нала или записать в определенный сектор диска). Под управлением контроллера устройство может некоторое время выполнять свои операции автономно, не тре­буя внимания со стороны центрального процессора. Это время зависит от мно­гих факторов — объема выводимой информации, степени интеллектуальности управляющего устройством контроллера, быстродействия устройства и т. п. Даже самый примитивный контроллер, выполняющий простые функции, обычно тра­тит довольно много времени на самостоятельную реализацию подобной функ­ции после получения очередной команды от процессора. Это же справедливо и для сложных контроллеров, так как скорость работы любого устройства ввода-вывода, даже самого скоростного, обычно существенно ниже скорости работы процессора.

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

Данная задача является классической задачей планирования систем реального времени и обычно решается на основе многоуровневой приоритетной схемы об­служивания по прерываниям. Для обеспечения приемлемого уровня реакции все драйверу (или части драйверов) распределяются по нескольким приоритетным уровням в соответствии с требованиями ко времени реакции и временем исполь­зования процессора. Для реализации приоритетной схемы обычно задействуется общий диспетчер прерываний ОС.

 

Согласование скоростей обмена и кэширование данных

 

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

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

Другим решением этой проблемы является использование большой буферной па­мяти в контроллерах внешних устройств. Такой подход особенно полезен в тех случаях, когда помещение данных на диск слишком замедляет обмен (или когда данные выводятся на сам диск). Например, в контроллерах графических диспле­ев применяется буферная память, соизмеримая по объему с оперативной, и это существенно ускоряет вывод графики на экран.

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

 

Разделение устройств и данных между процессами     

 

Устройства ввода-вывода могут предоставляться процессам как в монопольное, так и в совместное (разделяемое) использование. При этом ОС должна обеспечи­вать контроль доступа теми же способами, что и при доступе процессов к дру­гим ресурсам вычислительной системы — путем проверки прав пользователя или группы пользователей, от имени которых действует процесс, на выполнение той или иной операции над устройством. Например, определенной группе пользова­телей последовательный порт разрешено захватывать в монопольное владение, а другим пользователям это запрещено.

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

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

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

в свой раздел спул-файла.

 

Обеспечение удобного логического интерфейса между устройствами и остальной частью системы

 

Разнообразие устройств ввода-вывода делают особенно актуальной функцию ОС по созданию экранирующего логического интерфейса между периферийными, устройствами и приложениями. Практически все современные операционные системы поддерживают в качестве основы такого интерфейса файловую модель периферийных устройств, когда любое устройство выглядит для прикладного программиста последовательным набором байт, с которым можно работать с по­мощью унифицированных системных вызовов (например, read и write), задавая имя файла-устройства и смещение от начала последовательности байт. Для под­держания такого интерфейса подсистема ввода-вывода должна проделать нема­лую работу, учитывая разницу в организации операций обмена данными, напри­мер, с жестким диском и графическим терминалом.

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

 

Поддержка широкого спектра драйверов и простота включения нового драйвера в систему

 

Достоинством подсистемы ввода-вывода любой универсальной ОС является на­личие разнообразного набора драйверов для наиболее популярных периферийных устройств. Прекрасно спланированная и реализованная операционная сис­тема может потерпеть неудачу на рынке только из-за того, что в ее состав не включен достаточный набор драйверов и администраторы и пользователи выну­ждены искать нужный им драйвер для имеющегося у них внешнего устройства у производителей оборудования-«ли, что еще хуже, заниматься его разработкой. Именно в такой ситуации оказались пользователи первых версий OS/2, и, воз­можно, это обстоятельство послужило в свое время не последней причиной сда­чи позиций этой неплохой операционной системы, богатой на драйверы ОС Win­dows 3.x.

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

Драйвер взаимодействует, с одной стороны, с модулями ядра ОС (модулями подсистемы ввода-вывода, модулями системных вызовов, модулями подсистем управления процессами и памятью и т. д.), а с другой стороны — с контроллера­ми внешних устройств. Поэтому существуют два типа интерфейсов: интерфейс «драйвер-ядро» (Driver Kernel Interface, DKI) и интерфейс «драйвер-устройство» (Driver Device Interface, DDI). Интерфейс «драйвер-ядро» должен быть стандар­тизован в любом случае, а интерфейс «драйвер-устройство» имеет смысл стан­дартизировать тогда, когда подсистема ввода-вывода не разрешает драйверу не­посредственно взаимодействовать с аппаратурой контроллера, а выполняет эти операции самостоятельно. Экранирование драйвера от аппаратуры является весьма полезной функцией, так как драйвер в этом случае становится независимым от аппаратной платформы. Подсистема ввода-вывода может поддерживать несколь­ко различных типов интерфейсов DKI/DDI, предоставляя специфический ин­терфейс для устройств определенного класса. Так, в ОС Windows NT для драй­веров сетевых адаптеров существует интерфейс стандарта NDIS (Network Driver Interface Specification), в то время как драйверы сетевых транспортных протоко­лов взаимодействуют с верхними слоями сетевого программного обеспечения по интерфейсу TDI (Transport Driver Interface).

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

Для поддержки процесса разработки драйверов операционной системы обычно выпускается так называемый пакет DDK (Driver Development Kit), представляющий собой набор соответствующих инструментальных средств — библиотек, компиляторов и отладчиков.

 

Динамическая загрузка и выгрузка драйверов

 

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

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

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

 

Поддержка нескольких файловых систем

 

Диски представляют особый род периферийных устройств, так как именно на них хранится большая часть как пользовательских, так и системных данных. Дан­ные на дисках организуются в файловые системы, и свойства файловой системы во многом определяют свойства самой ОС — ее отказоустойчивость, быстродей­ствие, максимальный объем хранимых данных. Популярность файловой систе­мы часто приводит к ее миграции из «родной» ОС в другие операционные систе­мы — например, файловая система FAT появилась первоначально в MS-DOS, но затем была реализована в OS/2, семействе MS Windows и многих реализациях UNIX. Ввиду этого поддержка нескольких популярных файловых систем для под­системы ввода-вывода также важна, как и поддержка широкого спектра перифе­рийных устройств. Важно также, чтобы архитектура подсистемы ввода-вывода позволяла достаточно просто включать в ее состав новые типы файловых сис­тем, без необходимости переписывания кода. Обычно в операционной системе имеется специальный слой программного обеспечения, отвечающий за решение данной задачи, например слой VFS ( Virtual File System) в версиях UNIX на осно­ве кода System V Release 4.

 

Поддержка синхронных и асинхронных операций ввода-вывода

 

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

 

 

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

 

Многослойная модель подсистемы ввода-вывода

 

Общая схема

 

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

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

Обобщенная структура подсистемы ввода-вывода представлена на рис. 7.2.

 

 

 

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

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

 

Менеджер ввода-вывода

 

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

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

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

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

Еще одной функцией менеджера ввода-вывода является организация взаимодей­ствия модулей ввода-вывода с модулями других подсистем ОС, таких как под­система управления процессами, виртуальной памятью и другими.

Примерами подобного менеджера являются менеджер ввода-вывода ОС Windows NT, а также среда STREAMS, существующая во многих версиях операционной сис­темы UNIX. Менеджер ввода-вывода Windows NT организует взаимодействие между модулями с помощью пакетов запросов ввода-вывода — IRP (I/O Request Packet). Получив запрос от процедуры системного вызова, менеджер формирует IRP и передает его нужному драйверу. Драйвер после выполнения запрошенной операции возвращает ответ в виде другого IRP менеджеру, а тот, в свою очередь, может при необходимости передать этот IRP другому драйверу. Менеджер по­зволяет драйверам задавать взаимосвязи (bindings) между собой, и на основании информации о взаимосвязях и происходит передача пакетов IRP. Кроме того, менеджер Windows NT поддерживает динамическую загрузку-выгрузку драйве­ров без останова системы.

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

 

Многоуровневые драйверы

 

Первоначально термин «драйвер» применялся в достаточно узком смысле: под драйвером понимался программный модуль, который:

□   входит в состав ядра операционной системы, работая в привилегированном режиме;

□   непосредственно управляет внешним устройством, взаимодействуя с его кон­троллером с помощью команд ввода-вывода компьютера;

□   обрабатывает прерывания от контроллера устройства;

□предоставляет прикладному программисту удобный логический интерфейс работы с устройством, экранируя от него низкоуровневые детали управления устройством и организации его данных;

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

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

В описанной схеме драйверы не делились на слои. При этом они выполняли задачи разного уровня сложности: как самые примитивные, например просто по­следовательно передавали контроллеру байты для дальнейшего использования, так и достаточно сложные, связанные с отработкой протокола взаимодействия между модемами или вычерчиванием на экране математических кривых.

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

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

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

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

Рассмотрим, как общие принципы построения многоуровневых драйверов могут быть реализованы при управлении определенными типами внешних устройств.

В вертикальной подсистеме сетевых устройств, приведенной на рис. 7.2, аппа­ратными драйверами являются драйверы сетевых адаптеров, которые выполня­ют функции низкоуровневых канальных протоколов, таких как Ethernet, Frame Relay, ATM и других. Эти драйверы выполняют простые функции — они органи­зуют передачу кадров данных между компьютерами одной сети. Над ними рас­полагается слой модулей, которые реализуют функции более интеллектуальных протоколов сетевого уровня — IP и IPX, которые могут обеспечить взаимодейст­вие компьютеров разных сетей с произвольной топологией связей. Модули IP и IPX также могут быть оформлены как драйверы, хотя они находятся в промежу­точном программном слое и непосредственно с аппаратурой не взаимодействуют. Вообще, вертикальная подсистема управления сетевыми устройствами являет­ся примером эффективного многоуровнего подхода к организации драйверов — просто в силу того, что в ее основе лежит хорошо продуманная семиуровневая модель взаимодействия открытых систем OSI. И, хотя все семь уровней модели OSI обычно не выделяются в самостоятельные программные уровни, четыре уровня драйверов чаще всего присутствуют в подсистеме управления сетевыми устройствами. Над слоем драйверов сетевых протоколов располагается слой драйверов транспортных протоколов, таких как TCP/UDP, SPX и NetBEUI, ко­торые отвечают за надежную связь между компьютерами сети. Еще выше распо­ложен слой драйверов протоколов прикладного уровня (на рисунке — http, ftp и SMB), которые предоставляют пользователям сети конечные услуги по доступу к гипертекстовой информации, архивам файлов и многие другие.

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

В подсистеме управления дисками аппаратные драйверы поддерживают для верх­них уровней представление диска как последовательного набора блоков одина­кового размера, преобразуя вместе с контроллером номер блока в более сложный адрес, состоящий из номеров цилиндра, головки и сектора. Однако такие поня­тия, как «файл» и «файловая система», аппаратные драйверы дисков не поддер­живают — эти удобные для пользователя и программиста логические абстракции создаются на более высоком уровне программным обеспечением файловых сис­тем, которое в современных ОС также оформляется как драйвер, только высоко­уровневый. Наличие универсальной среды, создаваемой менеджером ввода-выво­да, позволяет достаточно просто решить проблему поддержки в ОС нескольких файловых систем одновременно. Для этого в ОС устанавливается несколько вы­сокоуровневых драйверов (на рисунке это драйверы файловых систем ufs, NTFS и FAT), работающих с общими аппаратными драйверами, но по-своему организую­щими хранение данных в блоках диска и по-своему представляющими файловую систему пользователю и прикладным процессам. Для унификации представле­ния различных файловых систем в подсистеме ввода-вывода может использо­ваться общий драйвер верхнего уровня, играющий роль диспетчера нескольких драйверов файловых систем. На рисунке в качестве примера показан диспетчер VFS (Virtual File System), применяемый в операционных системах UNIX, реали­зованных на основе кода System V Release 4.

Необязательно все модули подсистемы ввода-вывода оформляются в виде драй­веров. Например, в подсистеме управлениями дисками обычно имеется такой модуль, как дисковый кэш, который служит для кэширования блоков дисковых файлов в оперативной памяти. Достаточно специфические функции кэша дела­ют нецелесообразным оформление его в виде драйвера, взаимодействующего с другими модулями ОС только с помощью услуг менеджера ввода-вывода. Дру­гим примером модуля, который чаще всего не оформляется в виде драйвера, является диспетчер окон графического интерфейса. Иногда этот модуль вообще вы­носится из ядра ОС и реализуется в виде пользовательского процесса. Таким об­разом был реализован диспетчер окон (а также высокоуровневые графические драйверы) в Windows NT 3.5 и.3.51, но этот микро ядерный подход заметно за­медлял графические операции, поэтому в Windows NT 4.0 диспетчер окон и вы­сокоуровневые графические драйверы, а также графическая библиотека GDI были перенесены в пространство ядра.

Аппаратные драйверы после запуска операции ввода-вывода должны своевремен­но реагировать на завершение контроллером заданного действия, и для решения этой задачи они взаимодействуют с системой прерываний. Драйверы более вы­соких уровней вызываются уже не по прерываниям, а по инициативе аппарат­ных драйверов или драйверов вышележащего уровня. Не все процедуры аппа­ратного драйвера нужно вызывать по прерываниям, поэтому драйвер обычно име­ет определенную структуру, в которой выделяется секция обработки прерываний (Interrupt Service Routine, ISR), которая и вызывается при поступлении запроса от соответствующего устройства диспетчером прерываний. Диспетчер прерыва­ний можно считать частью подсистемы ввода-вывода, как это показано на рис. 7.2, а можно считать и независимым модулем ядра ОС, так как он служит не только для вызова секций обработки прерываний драйверов, но и для диспетчеризации прерываний других типов.

В унификацию драйверов большой вклад внесла операционная система UNIX. В ней все драйверы были разделены на два больших класса: блок-ориентирован­ные (block-oriented) драйверы и байт-ориентированные (character-oriented) драйверы. Это деление является более общим, чем показанное на рис. 7.2 деле­ние на вертикальные подсистемы. Например, драйверы графических устройств и драйверы сетевых устройств относятся к классу байт-ориентированных.

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

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

Значительность отличий блок-ориентированных и байт-ориентированных драй­веров иллюстрирует тот факт, что среда STREAMS разработана только для байт-ориентированных драйверов и включить в нее блок-ориентированный драйвер невозможно.

Блок- или байт-ориентированность является характеристикой как самого устрой­ства, так и драйвера. Очевидно, что если устройство не поддерживает обмен адресуемыми блоками данных, а позволяет записывать или считывать последовательность байт, то и устройство, и его драйвер можно назвать байт-ориентиро­ванными. Для байт-ориентированного устройства невозможно разработать блок-ориентированный драйвер. Устройство прямого доступа с блочной адресацией является блок-ориентированным, и для управления им естественно использовать блок-ориентированный драйвер. Однако блок-ориентированным устройством можно управлять и с помощью байт-ориентированного драйвера. Так, диск мож­но рассматривать не только как набор блоков, но и как набор байт, первый из ко­торых начинает первый блок диска, а последний завершает последний блок. Фи­зический обмен с контроллером устройства по-прежнему осуществляется блоками, но байт-ориентированный драйвер устройства будет преобразовывать блоки в последовательность байт. Для устройств прямого доступа часто разраба­тывают пару драйверов, чтобы к устройству можно было обращаться и по байт-ориентированному, и по блок-ориентированному интерфейсам в зависимости от потребностей.

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

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

 

Специальные файлы

 

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

Понятие специального файла появилось в операционной системе UNIX. Специ­альный файл всегда связан с некоторым устройством ввода-вывода и представ­ляет его для остальной части операционной системы и прикладных процессов в виде неструктурированного набора байт. Со специальным файлом можно рабо­тать так же, как и с обычным, то есть открывать, считывать из него определенное количество байт или же записывать в него определенное количество байт, а по­сле завершения операции закрывать. Для этоп5 используются те же системные вызовы, что и для работы с обычными файлами: open, create, read, write и close. Таким образом, для того чтобы вывести на алфавитно-цифровой терминал, с ко­торым связан специальный файл /dev/tty3, сообщение "Hello, friends!", доста­точно открыть этот файл с помощью системного вызова open:

 

Затем можно вывести сообщение с помощью системного вызова write:

 

 

Для устройств прямого доступа имеет смысл также указатель текущего положе­ния в файле, которым можно управлять с помощью системного вызова 1 seek.

Очевидно, что представление устройства в виде файла и использование для управления устройством файловых системных вызовов во многих случаях не по­зволяет выполнять только достаточно простые операции.

Традиционно специальные файлы помещаются в каталог /dev, хотя ничто не мешает создать их в любом каталоге файловой системы. При появлении ново­го устройства и соответственно нового драйвера администратор системы может создать новую запись с помощью команды mknod. Например, следующая команда создает блок-ориентированный специальный файл:

 

Логическая организация файловой системы

 

Одной из основных задач операционной системы является предоставление удобств пользователю при работе с данными, хранящимися на дисках. Для этого ОС под­меняет физическую структуру хранящихся данных некоторой удобной для поль­зователя логической моделью. Логическая модель файловой системы материа­лизуется в виде дерева каталогов, выводимого на экран такими утилитами, как Norton Commander или Windows Explorer, в символьных составных именах фай­лов, в командах работы с файлами. Базовым элементом этой модели является файл, который так же, как и файловая система в целом, может характеризовать­ся как логической, так и физической структурой.

 

Цели и задачи файловой системы

 

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

Основные цели использования файла перечислены ниже.

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

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

Файловая система (ФС) — это часть операционной системы, включающая:

□  совокупность всех файлов на диске;

□  наборы структур данных, используемых для управления файлами, такие, на­пример, как каталоги файлов, дескрипторы файлов, таблицы распределения свободного и занятого пространства на диске;

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

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

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

Задачи, решаемые ФС, зависят от способа организации вычислительного про­цесса в целом. Самый простой тип — это ФС в однопользовательских и однопрограммных ОС, к числу которых относится, например, MS-DOS. Основные функ­ции в такой ФС нацелены на решение следующих задач:

□ именование файлов;

□  программный интерфейс для приложений;

□  отображения логической модели файловой системы на физическую организа­цию хранилища данных;

□  устойчивость файловой системы к сбоям питания, ошибкам аппаратных и про­граммных средств.

Задачи ФС усложняются в операционных однопользовательских мультипро­граммных ОС, которые, хотя и предназначены для работы одного пользователя, но дают ему возможность запускать одновременно несколько процессов. Одной  из первых ОС этого типа стала OS/2. К перечисленным выше задачам добавляется новая задача совместного доступа к файлу из нескольких процессов. Файл в этом случае является разделяемым ресурсом, а значит, файловая система должна решать весь комплекс проблем, связанных с такими ресурсами. В частности, в ФС должны быть предусмотрены средства блокировки файла и его частей, пре­дотвращения гонок, исключение тупиков, согласование копий и т. п.

В многопользовательских системах появляется еще одна задача: защита файлов одного пользователя от несанкционированного доступа другого пользователя.

Еще более сложными становятся функции ФС, которая работает в составе сете­вой ОС. Эта тема рассматривается в последней главе книги, посвященной управ­лению сетевыми ресурсами.

 

Типы файлов

 

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

Обычные файлы, или просто файлы, содержат информацию произвольного харак­тера, которую заносит в них пользователь или которая образуется в результате работы системных и пользовательских программ. Большинство современных опе­рационных систем (например, UNIX, Windows, OS/2) никак не ограничивает и не контролирует содержимое и структуру обычного файла. Содержание обычно­го файла определяется приложением, которое с ним работает. Например, тексто­вый редактор создает текстовые файлы, состоящие из строк символов, представ­ленных в каком-либо коде. Это могут быть документы, исходные тексты программ и т. п. Текстовые файлы можно прочитать на экране и распечатать на принтере. Двоичные файлы не используют коды символов, они часто имеют сложную внут­реннюю структуру, например исполняемый код программы или архивный файл. Все операционные системы должны уметь распознавать хотя бы один тип фай­лов — их собственные исполняемые файлы.

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

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

 

Иерархическая структура файловой системы

 

Пользователи обращаются к файлам по символьным именам. Однако способ­ности человеческой памяти ограничивают количество имен объектов, к кото­рым пользователь может обращаться по имени. Иерархическая организация про­странства имен позволяет значительно расширить эти границы. Именно поэтому большинство файловых систем имеет иерархическую структуру, в которой уров­ни создаются за счет того, что каталог более низкого уровня может входить в ка­талог более высокого уровня (рис. 7.3).

 

 

 

 

 

 

Граф, описывающий иерархию каталогов, может быть деревом или сетью. Ката­логи образуют дерево, если файлу разрешено входить только в один каталог (рис. 7.3, б), и сеть — если файл может входить сразу в несколько каталогов (рис. 7.3, е). Например, в MS-DOS и Windows каталоги образуют древовидную структуру, а в UNIX — сетевую. В древовидной структуре каждый файл являет­ся листом. Каталог самого верхнего уровня называется корневым каталогом, или    корнем (root).

При такой организации пользователь освобожден от запоминания имен всех фай­лов, ему достаточно примерно представлять, к какой группе может быть отнесен тот или иной файл, чтобы путем последовательного просмотра каталогов найти его. Иерархическая структура удобна для многопользовательской работы: каж­дый пользователь со своими файлами локализуется в своем каталоге или подде­реве каталогов, и вместе с тем все файлы в системе логически связаны. Частным случаем иерархической структуры является одноуровневая организа­ция, когда все файлы входят в один каталог (рис. 7.3, а).

 

Имена файлов

 

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

Простое, или короткое, символьное имя идентифицирует файл в пределах одного каталога. Простые имена присваивают файлам пользователи и программисты, при этом они должны учитывать ограничения ОС как на номенклатуру символов, так и на длину имени. До сравнительно недавнего времени эти границы были весьма узкими. Так, в популярной файловой системе FAT длина имен ограничи­вались схемой 8.3 (8 символов — собственно имя, 3 символа — расширение имени), а в файловой системе s5, поддерживаемой многими версиями ОС UNIX, простое символьное имя не могло содержать более 14 символов. Однако пользователю гораздо удобнее работать с длинными именами, поскольку они позволяют дать файлам легко запоминающиеся названия, ясно говорящие о том, что содержится в этом файле. Поэтому современные файловые системы, а также усовершенство­ванные варианты уже существовавших файловых систем, как правило, поддер­живают длинные простые символьные имена файлов/Например, в файловых сис­темах NTFS и FAT32, входящих в состав операционной системы Windows NT, имя файла может содержать до 255 символов. Примеры простых имен файлов и каталогов:

 

 

В иерархических файловых системах разным файлам разрешено иметь одинако­вые простые символьные имена при условии, что они принадлежат разным ката­логам. То есть здесь работает схема «много файлов одно простое имя». Для однозначной идентификации файла в таких системах используется так называемое полное имя.

Полное имя представляет собой цепочку простых символьных имен всех катало­гов, через которые проходит путь от корня до данного файла. Таким образом, полное имя является составным, в котором простые имена отделены друг от друга принятым в ОС разделителем. Часто в качестве разделителя используется прямой или обратный слеш, при этом принято не указывать имя корневого ката­лога. На рис. 7.3, б два файла имеют простое имя main.exe, однако их составные имена /depart/main.ехе и /user/anna/main.exe различаются. В древовидной файловой системе между файлом и его полным именем имеется взаимно однозначное соответствие «один файл — одно полное имя». В файловых системах, имеющих сетевую структуру, файл может входить в несколько катало­гов, а значит, иметь несколько полных имен; здесь справедливо соответствие «один файл много полных имен». В обоих случаях файл однозначно идентифи­цируется полным именем.

Файл может быть идентифицирован также относительным именем. Относи­тельное имя файла определяется через понятие «текущий каталог». Для каждого пользователя в каждый момент времени один из каталогов файловой системы является текущим, причем этот каталог выбирается самим пользователем по ко­манде ОС. Файловая система фиксирует имя текущего каталога, чтобы затем использовать его как дополнение к относительным именам для образования пол­ного имени файла. При использовании относительных имен пользователь иден­тифицирует файл цепочкой имен каталогов, через которые проходит маршрут от текущего каталога до данного файла. Например, если текущим каталогом явля­ется каталог /user, то относительное имя файла /user/anna/main.exe выглядит следующим образом: anna/ main.exe.

В некоторых операционных системах разрешено присваивать одному и тому же файлу несколько простых имен, которые можно интерпретировать как псевдо­нимы. В этом случае, так же как в системе с сетевой структурой, устанавливается соответствие «один файл — много полных имен», так как каждому простому име­ни файла соответствует по крайней мере одно полное имя. И хотя полное имя однозначно определяет файл, операционной системе проще работать с файлом, если между файлами и их именами имеется взаимно одно­значное соответствие. С этой целью она присваивает файлу уникальное имя, так что справедливо соотношение «один файл одно уникальное имя». Уникальное имя существует наряду с одним или несколькими символьными именами, при­сваиваемыми файлу пользователями или приложениями. Уникальное имя пред­ставляет собой числовой идентификатор и предназначено только для опера­ционной системы. Примером такого уникального имени файла является номер индексного дескриптора в системе UNIX.

 

Монтирование

 

В общем случае вычислительная система может иметь несколько дисковых уст­ройств. Даже типичный персональный компьютер обычно имеет один накопитель

на жестком диске, один накопитель на гибких дисках и накопитель для компакт-дисков. Мощные же компьютеры, как правило, оснащены большим количеством дисковых накопителей, на которые устанавливаются пакеты дисков. Более того, даже одно физическое устройство с помощью средств операционной системы может быть представлено в виде нескольких логических устройств, в частности путем разбиения дискового пространства на разделы. Возникает вопрос, каким образом организовать хранение файлов в системе, имеющей несколько устройств внешней памяти?                              Первое решение состоит в том, что на каждом из устройств размещается авто­номная файловая система, то есть файлы, находящиеся на этом устройстве, описы­ваются деревом каталогов, никак не связанным с деревьями каталогов на других устройствах. В таком случае для однозначной идентификации файла пользова­тель наряду с составным символьным именем файла должен указывать иденти­фикатор логического устройства. Примером такого автономного существования файловых систем является операционная система MS-DOS, в которой полное имя файла включает буквенный идентификатор логического диска. Так, при об­ращении к файлу, расположенному на диске А, пользователь должен указать имя этого диска: A:\privat\letter\uni\let1.doc.

Другим вариантом является такая организация хранения файлов, при которой пользователю предоставляется возможность объединять файловые системы, на­ходящиеся на разных устройствах, в единую файловую систему, описываемую единым деревом каталогов. Такая операция называется монтированием. Рассмот­рим, как осуществляется эта операция на примере ОС UNIX.

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

Файловая система, расположенная на системном диске, назначается корневой. Для связи иерархий файлов в корневой файловой системе выбирается некото­рый существующий каталог, в данном примере — каталог man. После выполне­ния монтирования выбранный каталог man становится корневым каталогом вто­рой файловой системы. Через этот каталог монтируемая файловая система подсоединяется как поддерево к общему дереву (рис. 7.5).

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

 

 

Атрибуты файлов

 

Понятие «файл» включает не только хранимые им данные и имя, но и атрибу­ты. Атрибуты — это информация, описывающая свойства файла. Примеры воз­можных атрибутов файла:

□  тип файла (обычный файл, каталог, специальный файл и т. п.);

□   владелец файла;

□  создатель файла;                        

□   пароль для доступа к файлу;

□   информация о разрешенных операциях доступа к файлу;

□   времена создания, последнего доступа и последнего изменения;

□  текущий размер файла;

□   максимальный размер файла;

□  признак «только для чтения»;

□   признак «скрытый файл»;

□   признак «системный файл»;

□   признак «архивный файл»;

□   признак «двоичный/символьный»;

□   признак «временный» (удалить после завершения процесса);

□   признак блокировки;

□  длина записи в файле;

□   указатель на ключевое поле в записи;

□  длина ключа.

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

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

Значения атрибутов файлов могут непосредственно содержаться в каталогах, как это сделано в файловой системе MS-DOS (рис. 7.6, а). На рисунке представлена структура записи в каталоге, содержащая простое символьное имя и атрибуты

файла. Здесь буквами обозначены признаки файла: R — только для чтения, А — архивный, Н — скрытый, S — системный.   

 

 

 

Другим вариантом является размещение атрибутов в специальных таблицах, ко­гда в каталогах содержатся только ссылки на эти таблицы. Такой подход реали­зован, например, в файловой системе ufs ОС UNIX. В этой файловой системе структура каталога очень простая. Запись о каждом файле содержит короткое символьное имя файла и указатель на индексный дескриптор файла, так называ­ется в ufs таблица, в которой сосредоточены значения атрибутов файла (рис. 7.6, б).

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

 

Логическая организация файла

 

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

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

Модель файла, в соответствии с которой содержимое файла представляется неструктурированной последовательностью (потоком) байт, стала популярной вместе с ОС UNIX, а теперь она широко используется в большинстве современных ОС, в том числе в MS-DOS, Windows NT/2000, NetWare. Неструктурированная мо­дель файла позволяет легко организовать разделение файла между несколькими приложениями: разные приложения могут по-своему структурировать и интер­претировать данные, содержащиеся в файле.

Другая модель файла, которая применялась в ОС OS/360, DEC RSX и VMS, а в настоящее время используется достаточно редко, — это структурированный файл. В этом случае поддержание структуры файла поручается файловой системе. Файловая система видит файл как упорядоченную последовательность логи­ческих записей. Приложение может обращаться к ФС с запросами на ввод-вывод на уровне записей, например «считать запись 25 из файла FILE.DOC». ФС долж­на обладать информацией о структуре файла, достаточной для того, чтобы выде­лить любую запись. ФС предоставляет приложению доступ к записи, а вся даль­нейшая обработка данных, содержащихся в этой записи, выполняется приложе­нием. Развитием этого подхода стали системы управления базами данных (СУБД), которые поддерживают не только сложную структуру данных, но и взаимосвязи между ними.

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

Файловая система может использовать два способа доступа к логическим запи­сям: читать или записывать логические записи последовательно {последователь­ный доступ) или позиционировать файл на запись с указанным номером {пря­мой доступ).

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

К числу таких способов структуризации относится представление данных в виде записей, длина которых фиксирована в пределах файла (рис. 7.7, а). В таком случае доступ к n-й записи осуществляется либо путем последовательного чтение (п-1) предшествующих записей, либо прямо по адресу, вычисленному по ее по­рядковому номеру. Например, если L — длина записи, то начальный адрес n-й записи равен L x n. Заметим, что при такой логической организации размер запи­си фиксирован в пределах файла, а записи в различных файлах, принадлежащих одной и той же файловой системе, могут иметь различный размер.

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

Файлы, доступ к записям которых осуществляется последовательно, по номерам позиций, называются неиндексированными, или последовательными.

 

 

 

Другим типом файлов являются индексированные файлы, они допускают более быстрый прямой доступ к отдельной логической записи. В индексированном файле (рис. 7.7, в) записи имеют одно или более ключевых (индексных) полей и могут адресоваться путем указания значений этих полей. Для быстрого поиска данных в индексированном файле предусматривается специальная индексная таблица, в которой значениям ключевых полей ставится в соответствие адрес внешней памяти. Этот адрес может указывать либо непосредственно на искомую запись, либо на некоторую область внешней памяти, занимаемую несколькими записями, в число которых входит искомая запись. В последнем случае говорят, что файл имеет индексно-последовательную организацию, так как поиск включа­ет два этапа: прямой доступ по индексу к указанной области диска, а затем по­следовательный просмотр записей в указанной области. Ведение индексных таб­лиц берет на себя файловая система. Понятно, что записи в индексированных файлах могут иметь произвольную длину.

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

 

Физическая организация файловой системы

 

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

 

Диски, разделы, секторы, кластеры

 

Основным типом устройства, которое используется в современных вычислитель­ных системах для хранения файлов, являются дисковые накопители. Эти уст­ройства предназначены для считывания и записи данных на жесткие и гибкие магнитные диски. Жесткий диск состоит из одной или нескольких стеклянных или металлических пластин, каждая из которых покрыта с одной или двух сто­рон магнитным материалом. Таким образом, диск в общем случае состоит из па­кета пластин (рис. 7.8).

На каждой стороне каждой пластины размечены тонкие концентрические коль­ца — дорожки (traks), на которых хранятся данные. Количество дорожек зависит от типа диска. Нумерация дорожек начинается с 0 от внешнего края к центру диска. Когда диск вращается, элемент, называемый головкой, считывает двоич­ные данные с магнитной дорожки или записывает их на магнитную дорожку.

 

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

Совокупность дорожек одного радиуса на всех поверхностях всех пластин паке­та называется цилиндром (cylinder). Каждая дорожка разбивается на фрагменты, называемые секторами (sectors), или блоками (blocks), так что все дорожки име­ют равное число секторов, в которые можно максимально записать одно и то же число байт. Сектор имеет фиксированный для конкретной системы размер, вы­ражающийся степенью двойки. Чаще всего размер сектора составляет 512 байт. Учитывая, что дорожки разного радиуса имеют одинаковое число секторов, плот­ность записи становится тем выше, чем ближе дорожка к центру.

Сектор — наименьшая адресуемая единица обмена данными дискового устройст­ва с оперативной памятью. Для того чтобы контроллер мог найти на диске нуж­ный сектор, необходимо задать ему все составляющие адреса сектора: номер ци­линдра, номер поверхности и номер сектора. Так как прикладной программе в общем случае нужен не сектор, а некоторое количество байт, не обязательно кратное размеру сектора, то типичный запрос включает чтение нескольких сек­торов, содержащих требуемую информацию, и одного или двух секторов, содер­жащих наряду с требуемыми избыточные данные (рис. 7.9).

 

 

Операционная система при работе с диском использует, как правило, собствен­ную единицу дискового пространства, называемую кластером {cluster). При соз­дании файла место на диске ему выделяется кластерами. Например, если файл имеет размер 2560 байт, а размер кластера в файловой системе определен в 1024 байта, то файлу будет выделено на диске 3 кластера.

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

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

Прежде чем форматировать диск под определенную файловую систему, он мо­жет быть разбит на разделы. Раздел — это непрерывная часть физического диска, которую операционная система представляет пользователю как логическое уст­ройство (используются также названия логический диск и логический раздел). Логическое устройство функционирует так, как если бы это был отдельный фи­зический диск. Именно с логическими устройствами работает пользователь, об­ращаясь к ним по символьным именам, используя, например, обозначения А, В, С, SYS и т. п. Операционные системы разного типа используют единое для всех них представление о разделах, но создают на его основе логические устройства, специфические для каждого типа ОС. Так же как файловая система, с которой работает одна ОС, в общем случае не может интерпретироваться ОС другого типа, логические устройства не могут быть использованы операционными систе­мами разного типа. На каждом логическом устройстве может создаваться только одна файловая система.

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

На разных логических устройствах одного и того же физического диска могут располагаться файловые системы разного типа. На рис. 7.10 показан пример дис­ка, разбитого на три раздела, в которых установлены две файловых системы NTFS (разделы С и Е) и одна файловая система FAT (раздел D).

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

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

 

Физическая организация и адресация файла

 

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

□   скорость доступа к данным;

□   объем адресной информации файла;

□   степень фрагментированности дискового пространства;

□   максимально возможный размер файла.

Непрерывное размещение — простейший вариант физической организации (рис. 7.11, а), при котором файлу предоставляется последовательность кластеров диска, образующих непрерывный участок дисковой памяти. Основным достоин­ством этого метода является высокая скорость доступа, так как затраты на поиск и считывание кластеров файла минимальны. Также минимален объем адресной информации — достаточно хранить только номер первого кластера и объем фай­ла. Данная физическая организация максимально возможный размер файла не ограничивает. Однако этот вариант имеет существенные недостатки, которые за­трудняют его применимость на практике, несмотря на всю его логическую про­стоту. При более пристальном рассмотрении оказывается, что реализовать эту схему не так уж просто. Действительно, какого размера должна быть непрерыв­ная область, выделяемая файлу, если файл при каждой модификации может уве­личить свой размер? Еще более серьезной проблемой является фрагментация. Спустя некоторое время после создания файловой системы в результате выпол­нения многочисленных операций создания и удаления файлов пространство дис­ка неминуемо превращается в «лоскутное одеяло», включающее большое число свободных областей небольшого размера. Как всегда бывает при фрагментации, суммарный объем свободной памяти может быть очень большим, а выбрать место для размещения файла целиком невозможно. Поэтому на практике используют­ся методы, в которых файл размещается в нескольких, в общем случае несмеж­ных областях диска.

 

 

Следующий способ физической организации — размещение файла в виде свя­занного списка кластеров дисковой памяти (рис. 7.11, б). При таком способе в начале каждого кластера содержится указатель на следующий кластер. В этом случае адресная информация минимальна: расположение файла может быть за­дано одним числом — номером первого кластера. В отличие от предыдущего спо­соба каждый кластер может быть присоединен к цепочке кластеров какого-либо файла, следовательно, фрагментация на уровне кластеров отсутствует. Файл мо­жет изменять свой размер во время своего существования, наращивая число кла­стеров. Недостатком является сложность реализации доступа к произвольно заданному месту файла — чтобы прочитать пятый по порядку кластер файла, не­обходимо последовательно прочитать четыре первых кластера, прослеживая цепочку номеров кластеров. Кроме того, при этом способе количество данных файла, содержащихся в одном кластере, не равно степени двойки (одно слово из­расходовано на номер следующего кластера), а многие программы читают дан­ные кластерами, размер которых равен степени двойки.

Популярным способом, применяемым, например, в файловой системе FAT, яв­ляется использование связанного списка индексов (рис. 7.11, в). Этот способ яв­ляется некоторой модификацией предыдущего. Файлу также выделяется память в виде связанного списка кластеров. Номер первого кластера запоминается в записи каталога, где хранятся характеристики этого файла. Остальная адресная информация отделена от кластеров файла. С каждым кластером диска связыва­ется некоторый элемент — индекс. Индексы располагаются в отдельной области диска — в MS-DOS это таблица FAT (File Allocation Table), занимающая один кластер. Когда память свободна, все индексы имеют нулевое значение. Если неко­торый кластер N назначен некоторому файлу, то индекс этого кластера становит­ся равным либо номеру М следующего кластера данного файла, либо принимает специальное значение, являющееся признаком того, что этот кластер является для файла последним. Индекс же предыдущего кластера файла принимает зна­чение N, указывая на вновь назначенный кластер.

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

ПРИМЕЧАНИЕ ----------------------------------------------------------------------------------------------

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

 

Еще один способ задания физического расположения файла заключается в про­стом перечислении номеров кластеров, занимаемых этим файлом (рис. 7.11, г). Этот перечень и служит адресом файла. Недостаток данного способа очевиден: длина адреса зависит от размера файла и для большого файла может составить значительную величину. Достоинством же является высокая скорость доступа к произвольному кластеру файла, так как здесь применяется прямая адресация, которая исключает просмотр цепочки указателей при поиске адреса произвольного кластера файла. Фрагментация на уровне кластеров в этом способе также отсутствует.

Последний подход с некоторыми модификациями используется в традиционных файловых системах ОС UNIX s5 и ufs1. Для сокращения объема адресной ин­формации прямой способ адресации сочетается с косвенным. В стандартной на сегодняшний день для UNIX файловой системе ufs использу­ется следующая схема адресации кластеров файла. Для хранения адреса файла выделено 15 полей, каждое из которых состоит из 4 байт (рис. 7.12). Если размер файла меньше или равен 12 кластерам, то номера этих кластеров непосредствен­но перечисляются в первых двенадцати полях адреса. Если кластер имеет размер 8 Кбайт (максимальный размер кластера, поддерживаемого в ufs), то таким обра­зом можно адресовать файл размером до 8192x12 = 98 304 байт.

 

Если размер файла превышает 12 кластеров, то следующее 13-е поле содержит адрес кластера, в котором могут быть расположены номера следующих класте­ров файла. Таким образом, 13-й элемент адреса используется для косвенной адресации. При размере в 8 Кбайт кластер, на который указывает 13-й элемент, может содержать 2048 номеров следующих кластеров данных файла и размер файла может возрасти до 8192х(12+2048)=16 875 520 байт.

Если размер файла превышает 12+2048 = 2060 кластеров, то используется 14-е поле,   Я в котором находится номер кластера, содержащего 2048 номеров кластеров, каждый из которых хранят 2048 номеров кластеров данных файла. Здесь применяет­ся уже двойная косвенная адресация. С ее помощью можно адресовать кластеры в файлах, содержащих до 8192х(12+2048+20482) = 3,43766хЮ10 байт.

И наконец, если файл включает более 12+2048+20482 = 4 196 364 кластеров, то используется последнее 15-е поле для тройной косвенной адресации, что позво­ляет задать адрес файла, имеющего следующий максимальный размер:

8192х(12+2048+20482+20483)=7,0403х1013байт.

Таким образом, файловая система ufs при размере кластера в 8 Кбайт поддержи­вает файлы, состоящие максимум из 70 триллионов байт данных, хранящихся в 8 миллиардах кластеров. Как видно на рис. 7.12, для задания адресной информа­ции о максимально большом файле требуется: 15 элементов по 4 байта (60 байт) в центральной части адреса плюс 1+(1+2048)+(1+2048+20482) = 4 198 403 кла­стера в косвенной части адреса. Несмотря на огромную величину, это число со­ставляет всего около 0,05 % от объема адресуемых данных.

Файловая система ufs поддерживает дисковые кластеры и меньших размеров, при этом максимальный размер файла будет другим. Используемая в более ранних версиях UNIX файловая система s5 имеет аналогичную схему адресации, но она рассчитана на файлы меньших размеров, поэтому в ней используется 13 адрес­ных элементов вместо 15.

Метод перечисления адресов кластеров файла задействован и в файловой систе­ме NTFS, используемой в ОС Windows NT/2000. Здесь он дополнен достаточно естественным приемом, сокращающим объем адресной информации: адресуются не кластеры файла, а непрерывные области, состоящие из смежных кластеров диска. Каждая такая область, называемая отрезком {run), или экстентом {extent), описывается с помощью двух чисел: начального номера кластера и количества кластеров в отрезке. Так как для сокращения времени операции обмена ОС ста­рается разместить файл в последовательных кластерах диска, то в большинстве случаев количество последовательных областей файла будет меньше количества кластеров файла и объем служебной адресной информации в NTFS сокращается по сравнению со схемой адресации файловых систем ufs/s5.

Для того чтобы корректно принимать решение о выделении файлу набора кла­стеров, файловая система должна отслеживать информацию о состоянии всех кластеров диска: свободен/занят. Эта информация может храниться как отдель­но от адресной информации файлов, так и вместе с ней.

 

Физическая организация FAT

 

Логический раздел, отформатированный под файловую систему FAT, состоит из следующих областей (рис. 7.13).

Загрузочный сектор содержит программу начальной загрузки операционной системы. Вид этой программы зависит от типа операционной системы, кото­рая будет загружаться из этого раздела.

□   Основная копия FA T содержит информацию о размещении файлов и катало­гов на диске.

□  Резервная копия FAT.

□  Корневой каталог занимает фиксированную область размером в 32 сектора (16 Кбайт), что позволяет хранить 512 записей о файлах и каталогах, так как каждая запись каталога состоит из 32 байт.

□   Область данных предназначена для размещения всех файлов и всех катало­гов, йроме корневого каталога.

 

 

Файловая система FAT поддерживает всего два типа файлов: обычный файл и каталог. Файловая система распределяет память только из области данных, при­чем использует в качестве минимальной единицы дискового пространства клас­тер.

Таблица FAT (как основная копия, так и резервная) состоит из массива индекс­ных указателей, количество которых равно количеству кластеров области дан­ных. Между кластерами и индексными указателями имеется взаимно однознач­ное соответствие — нулевой указатель соответствует нулевому кластеру и т. д.

Индексный указатель может принимать следующие значения, характеризующие состояние связанного с ним кластера:

□   кластер свободен (не используется);

□   кластер используется файлом и не является последним кластером файла; в этом случае индексный указатель содержит номер следующего кластера файла;

□  последний кластер файла;

дефектный кластер;

□   резервный кластер.

Таблица FAT является общей для всех файлов раздела. В исходном состоянии (после форматирования) все кластеры раздела свободны и все индексные указа­тели (кроме тех, которые соответствуют резервным и дефектным блокам) при­нимают значение «кластер свободен». При размещении файла ОС просматривает FAT, начиная с начала, и ищет первый свободный индексный указатель. После его обнаружения в поле записи каталога «номер первого кластера» (см. рис. 7.6, а) фиксируется номер этого указателя. В кластер с этим номером записываются данные файла, он становится первым кластером файла. Если файл умещается в одном кластере, то в указатель, соответствующий данному кластеру, заносится специальное значение «последний кластер файла». Если же размер файла боль­ше одного кластера, то ОС продолжает просмотр FAT и ищет следующий указа­тель на свободный кластер. После его обнаружения в предыдущий указатель за­носится номер этого кластера, который теперь становится следующим кластером файла. Процесс повторяется до тех пор, пока не будут размещены все данные файла. Таким образом создается связный список всех кластеров файла.

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

Размер таблицы FAT и разрядность используемых в ней индексных указателей определяется количеством кластеров в области данных. Для уменьшения потерь из-за фрагментации желательно кластеры делать небольшими, а для сокраще­ния объема адресной информации и повышения скорости обмена наоборот — чем больше, тем лучше. При форматировании диска под файловую систему FAT обычно выбирается компромиссное решение и размеры кластеров выбираются из диапазона от 1 до 128 секторов, или от 512 байт до 64 Кбайт.

Очевидно, что разрядность индексного указателя должна быть такой, чтобы в нем можно было задать максимальный номер кластера для диска определенного объема. Существует несколько разновидностей FAT, отличающихся разрядностью индексных указателей, которая и используется в качестве условного обозначе­ния: FAT 12, FAT16 и FAT32. В файловой системе FAT12 используются 12-раз­рядные указатели, что позволяет поддерживать до 4096 кластеров в области дан­ных диска, в FAT16 — 16-разрядные указатели для 65 536 кластеров и в FAT32 — 32-разрядные для более чем 4 миллиардов кластеров.

 

Форматирование FAT 12 обычно характерно только для небольших дисков объ­емом не более 16 Мбайт, чтобы не использовать кластеры более 4 Кбайт. По этой же причине считается, что FAT16 целесообразнее для дисков с объемом не более 512 Мбайт, а для больших дисков лучше подходит FAT32, которая способна ис­пользовать кластеры 4 Кбайт при работе с дисками объемом до 8 Гбайт и только для дисков большего объема начинает использовать 8, 16 и 32 Кбайт. Макси­мальный размер раздела FAT16 ограничен 4 Гбайт, такой объем дает 65 536 кла­стеров по 64 Кбайт каждый, а максимальный размер раздела FAT32 практически не ограничен — 232 кластеров по 32 Кбайт.

Таблица FAT при фиксированной разрядности индексных указателей имеет пе­ременный размер, зависящий от объема области данных диска.

При удалении файла из файловой системы FAT в первый байт соответствующей записи каталога заносится специальный признак, свидетельствующий о том, что эта запись свободна, а во все индексные указатели файла заносится признак «кла­стер свободен». Остальные данные в записи каталога, в том числе номер первого кластера файла, остаются нетронутыми, что оставляет шансы для восстановле­ния ошибочно удаленного файла. Существует большое количество утилит для восстановления удаленных файлов FAT, выводящих пользователю список имен удаленных файлов с отсутствующим первым символом имени, затертым после 

освобождения записи. Очевидно, что надежно можно восстановить только фай­лы, которые были расположены в последовательных кластерах диска, так как при : отсутствии связного списка выявить принадлежность произвольно расположен­ного кластера удаленному файлу невозможно (без анализа содержимого класте­ров, выполняемого пользователем_«вручную»).

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

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

Файловые системы FAT 12 и FAT 16 оперировали с именами файлов, состоящи­ми из 12 символов по схеме «8.3». В версии FAT16 операционной системы Win­dows NT был введен новый тип записи каталога — «длинное имя», что позволяет использовать имена длиной до 255 символов, причем каждый символ длинного имени хранится в двухбайтном формате Unicode. Имя по схеме «8.3», названное теперь коротким (не нужно путать его с простым именем файла, также называе­мого иногда коротким), по-прежнему хранится в 12-байтовом поле имени файла в записи каталога, а длинное имя помещается порциями по 13 символов в одну или несколько записей, следующих Непосредственно за основной записью ката­лога. Каждый символ в формате Unicode кодируется двумя байтами, поэтому 13 символов занимают 26 байт, а оставшиеся 6 отведены под служебную инфор­мацию. Таким образом у файла появляются два имени — короткое, для совмес­тимости со старыми приложениями, не понимающими длинных имен в Unicode, и длинное, удобное в использовании имя. Файловая система FAT32 также под­держивает короткие и длинные имена.

Файловые системы FAT12 и FAT16 получили большое распространение благо­даря их применению в операционных системах MS-DOS и Windows 3.x — самых массовых операционных системах первого десятилетия эры персональных ком­пьютеров. По этой причине эти файловые системы поддерживаются сегодня и другими ОС, такими как UNIX, OS/2, Windows NT/2000 и Windows 95/98. Од­нако из-за постоянно растущих объемов жестких дисков, а также возрастающих требований к надежности, эти файловые системы быстро вытесняются как сис­темой FAT32, впервые появившейся в Windows 95 OSR2, так и файловыми сис­темами других типов.

 

Физическая организация s5 и ufs

 

Файловые системы s5 (получившие название от System V, родового имени не­скольких версий ОС UNIX, разработанных в Bell Labs компании AT&T) и ufs (UNIX File System) используют очень близкую физическую модель. Это не удивительно, так как система ufs является развитием системы s5. Файловая система ufs расширяет возможности s5 по поддержке больших дисков и файлов, а также повышает ее надежность.

ВНИМАНИЕ---------------------------------------------------------------------------------------------------В этом разделе вместо термина «кластер» будет использоваться термин «блок», как это принято в файловых системах UNIX.

 

Расположение файловой системы s5 на диске иллюстрирует рис. 7.15. Раздел дис­ка, где размещается файловая система, делится на четыре области:

□  загрузочный блок;

□  суперблок (superblock) содержит самую общую информацию о файловой сис­теме: размер файловой системы, размер области индексных дескрипторов, чис­ло индексных дескрипторов, список свободных блоков и список свободных индексных дескрипторов, а также другую административную информацию;

область индексных дескрипторов (tnode list), порядок расположения индекс­ных дескрипторов в которой соответствует их номерам;

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

 

 

Основной особенностью физической организации файловой системы s5 являет­ся отделение имени файла от его характеристик, хранящихся в отдельной струк­туре, называемой индексным дескриптором (inode). Индексный дескриптор в s5

имеет размер 64 байта и содержит данные о типе файла, адресную информацию, привилегии доступа к файлу и некоторую другую информацию:

□   идентификатор владельца файла;

□  тип файла; файл может быть файлом обычного типа, каталогом, специальным файлом, а также конвейером или символьной связью;

□  права доступа к файлу;

□  временные характеристики: время Последней модификации файла, время по­следнего обращения к файлу, время последней модификации индексного де­скриптора;

□  число ссылок на данный индексный дескриптор, равный количеству псевдо­нимов файла;

□  адресная информация (структура адреса рассмотрена выше в разделе «Физи­ческая организация и адресация файла»);

□   размер файла в байтах.

Каждый индексный дескриптор имеет номер, который одновременно является уникальным именем файла. Индексные дескрипторы расположены в особой об­ласти диска в строгом соответствии со своими номерами. Соответствие между полными символьными именами файлов и их уникальными именами устанав­ливается с помощью иерархии каталогов. Система ведет список номеров свобод­ных индексных дескрипторов. При создании файла ему выделяется номер из этого списка, а при уничтожении файла номер его индексного дескриптора воз­вращается в список.

Запись о файле в каталоге состоит всего из двух полей: символьного имени фай­ла и номера индексного дескриптора. Например, на рис. 7.16 показана информа­ция, содержащаяся в каталоге /user.

 

Файловая система не накладывает особых ограничений на размер корневого каталога, так как он расположен в области данных и может увеличиваться как

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

 

 

Рассмотрим эту процедуру на примере файла /bin/my_shell/print, входящего в со­став файловой системы, изображенной на рис. 7.17. Определение физического адреса этого файла включает следующие этапы.

1.   Прежде всего просматривается корневой каталог с целью поиска первой со­ставляющей символьного имени — bin. Определяется номер (в данном приме­ре — 6) индексного дескриптора каталога, входящего в корневой каталог. Адрес корневого каталога известен системе.

2.   Из области индексных дескрипторов считывается дескриптор с номером 6. Начальный адрес дескриптора определяется на основании известных систе­ме номера начального сектора области индексных дескрипторов и размера индексного дескриптора. Из индексного дескриптора 6 определяется физиче­ский адрес каталога /bin.

3.   Просматривается каталог /bin с целью поиска второй составляющей символь­ного имени my_shell. Определяется номер индексного дескриптора каталога /bin/my_shell (в данном случае — 25).

4.   Считывается индексный дескриптор 25, определяется физический адрес /bin/my_shell.

5.   Просматривается каталог /bin/my_shell, определяется номер индексного деск­риптора файла print (в данном случае — 131).

6.   Из индексного дескриптора 131 определяются номера блоков данных, а также другие характеристики файла /bin/my_shell/print.

Эта процедура требует в общем случае нескольких обращений к диску, пропорцио­нально числу составляющих в полном имени файла. Для уменьшения среднего вре­мени доступа к файлу его дескриптор копируется в специальную системную область оперативной памяти. Копирование индексного дескриптора входит в процедуру от­крытия файла.

Физическая организация файловой системы ufs отличается от описанной физи­ческой организации файловой системы s5 тем, что раздел состоит из повторяю­щейся несколько раз последовательности областей «загрузчик—суперблок—блок группы цилиндров—область индексных дескрипторов» (рис. 7.18).

 

 

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

Кроме того, в ufs имена файлов могут иметь длину до 255 символов (кодировка ASCII, по одному байту на символ), в то время как в s5 длина имени не может превышать 14 символов.

 

 

Физическая организация NTFS

 

Файловая система NTFS была разработана в качестве основной файловой системы для ОС Windows NT в начале 90-х годов с учетом опыта разработки файловых систем FAT и HPFS (основная файловая система для OS/2), а также других су­ществовавших в то время файловых систем. Основными отличительными свой­ствами NTFS являются:

□  поддержка больших файлов и больших дисков объемом до 264 байт;

□  восстанавливаемость после сбоев и отказов программ и аппаратуры управле­ния дисками;

□   высокая скорость операций, в том числе и для больших дисков;

□  низкий уровень фрагментации, в том числе и для больших дисков;

□ гибкая структура, допускающая развитие за счет добавления новых типов за­писей и атрибутов файлов с сохранением совместимости с предыдущими вер­сиями ФС;

□  устойчивость к отказам дисковых накопителей;

□  поддержка длинных символьных имен;

□   контроль доступа к каталогам и отдельным файлам.

 

Структура тома NTFS

 

В отличие от разделов FAT и s5/ufs все пространство тома NTFS представляет собой либо файл, либо часть файла. Основой структуры тома NTFS является главная таблица файлов {Master File Table, MFT), которая содержит по крайней мере одну запись для каждого файла тома, включая одну запись для самой себя. Каждая запись MFT имеет фиксированную длину, зависящую от объема дис­ка, — 1,2 или 4 Кбайт. Для большинства дисков, используемых сегодня, размер записи MFT равен 2 Кбайт, который мы далее будет считать размером записи по умолчанию.

Все файлы на томе NTFS идентифицируются номером файла, который определяется позицией файла в MFT. Этот способ идентификации файла близок к способу, исполь­зуемому в файловых системах s5 и ufs, где файл однозначно идентифицируется номе­ром его записи в области индексных дескрипторов.

Весь том NTFS состоит из последовательности кластеров, что отличает эту фай­ловую систему от рассмотренных ранее, где на кластеры делилась только область данных. Порядковый номер кластера в томе NTFS называется логическим номе­ром кластера {Logical Cluster Number, LCN). Файл NTFS также состоит из после­довательности кластеров, при этом порядковый номер кластера внутри файла называется виртуальным номером кластера {Virtual Cluster Number, VCN).

Базовая единица распределения дискового пространства для файловой системы NTFS — непрерывная область кластеров, называемая отрезком. В качестве адре­са отрезка NTFS использует логический номер его первого кластера, а также ко­личество кластеров в отрезке к, то есть пара (LCN, к). Таким образом, часть файла, помещенная в отрезок и начинающаяся с виртуального кластера VCN, ха­рактеризуется адресом, состоящим из трех чисел: (VCN, LCN, к). Для хранения номера кластера в NTFS используются 64-разрядные указатели, что дает возможность поддерживать тома и файлы размером до 2 64 кластеров. При размере кластера в 4 Кбайт это позволяет использовать тома и файлы, со­стоящие из 64 миллиардов килобайт.

Структура тома NTFS показана на рис. 7.19. Загрузочный блок тома NTFS рас­полагается в начале тома, а его копия — в середине тома. Загрузочный блок со­держит стандартный блок параметров BIOS, количество блоков в томе, а также начальный логический номер кластера основной копии MFT и зеркальную ко­пию MFT.

 

Далее располагается первый отрезок MFT, содержащий 16 стандартных, созда­ваемых при форматировании записей о системных файлах NTFS. Назначение этих файлов описано в показанной ниже таблице MFT.

 

В NTFS файл целиком размещается в записи таблицы MFT, если это позволяет сделать его размер. В том же случае, когда размер файла больше размера записи MFT, в запись помещаются только некоторые атрибуты файла, а остальная часть файла размещается в отдельном отрезке тома (или нескольких отрезках). Часть файла, размещаемая в записи MFT, называется резидентной частью, а остальные, части — нерезидентными. Адресная информация об отрезках, содержащих нере­зидентные части файла, размещается в атрибутах резидентной части.

Некоторые системные файлы являются полностью резидентными, а некоторые имеют и нерезидентные части, которые располагаются после первого отрезка MFT.

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

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

 

Структура файлов NTFS

 

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

Каждый атрибут файла NTFS состоит из полей: тип атрибута, длина атрибута, значение атрибута и, возможно, имя атрибута. Тип атрибута, длина и имя обра­зуют заголовок атрибута.

Имеется системный набор атрибутов, определяемых структурой тома NTFS. Сис­темные атрибуты имеют фиксированные имена и коды их типа, а также опреде­ленный формат. Могут применяться также атрибуты, определяемые пользова­телями. Их имена, типы и форматы задаются исключительно пользователем. Атрибуты файлов упорядочены по убыванию кода атрибута, причем атрибут од­ного и того же типа может повторяться несколько раз. Существуют два способа хранения атрибутов файла — резидентное хранение в записях таблицы MFT и нерезидентное хранение вне ее, во внешних отрезках. Таким образом, резидент­ная часть файла состоит из резидентных атрибутов, а нерезидентная — из нере­зидентных атрибутов. Сортировка может осуществляться только по резидентным атрибутам.

Системный набор включает следующие атрибуты:

□  Attribute List (список атрибутов) — список атрибутов, из которых состоит файл; содержит ссылки на номер записи MFT, где расположен каждый атри­бут; этот редко используемый атрибут нужен только в том случае, если атри­буты файла не умещаются в основной записи и занимают дополнительные за­писи MFT;

□  File Name (имя файла) — этот атрибут содержит длинное имя файла в форма­те Unicode, а также номер входа в таблице MFT для родительского каталога; если этот файл содержится в нескольких каталогах, то у него будет несколько атрибутов типа File Name; этот атрибут всегда должен быть резидентным;

□  MS-DOS Name (имя MS-DOS) — этот атрибут содержит имя файла в форма­те 8.3;

□   Version (версия) — атрибут содержит номер последней версии файла;

□  Security Descriptor (дескриптор безопасности) — этот атрибут содержит ин­формацию о защите файла: список прав доступа ACL (права доступа к файлу рассматриваются ниже в разделе «Контроль доступа к файлам») и поле ауди­та, которое определяет, какого рода операции над этим файлом нужно регист­рировать;

□   Volume Version (версия тома) — версия тома, используется только в систем­ных файлах тома;

□   Volume Name (имя тома) — имя тома;

□  Data (данные) — содержит обычные данные файла;

□  MFT bitmap (битовая карта MFT) — этот атрибут содержит карту использо­вания блоков на томе;

□  Index Root (корень индекса) — корень В-дерева, используемого для поиска фай­лов в каталоге;

□  Index Allocation (размещение индекса) — нерезидентные части индексного списка В-дерева;

□  Standard Information (стандартная информация) — этот атрибут хранит всю остальную стандартную информацию о файле, которую трудно связать с ка­ким-либо из других атрибутов файла, например, время создания файла, вре­мя обновления и другие.

Файлы NTFS в зависимости от способа размещения делятся на небольшие, боль­шие, очень большие и сверхбольшие.

Небольшие файлы (small). Если файл имеет небольшой размер, то он может цели­ком располагаться внутри одной записи MFT, имеющей, например, размер 2 Кбайт. Небольшие файлы NTFS состоят по крайней мере из следующих атри­бутов (рис. 7.20):

□   стандартная информация (SI — standard information);

имя файла (FN — file name);

□  данные (Data);

□  дескриптор безопасности (SD — security descriptor).

Из-за того что файл может иметь переменное количество атрибутов, а также из-за переменного размера атрибутов нельзя наверняка утверждать, что файл уме­стится внутри записи. Однако обычно файлы размером менее 1500 байт помеща­ются внутри записи MFT (размером 2 Кбайт).

 

Большие файлы (large). Если данные файла не помещаются в одну запись MFT, то этот факт отражается в заголовке атрибута Data, который содержит признак того, что этот атрибут является нерезидентным, то есть находится в отрезках вне таблицы MFT. В этом случае атрибут Data содержит адресную информацию (LCN, VCN, к) каждого отрезка данных (рис. 7.21).

 

 

 

 

Сверхбольшие файлы (extremely huge). Для сверхбольших файлов в атрибуте Attribute List можно указать несколько атрибутов, расположенных в дополни­тельных записях MFT (рис. 7.23). Кроме того, можно использовать двойную косвенную адресацию, когда нерезидентный атрибут будет ссылаться на другие нерезидентные атрибуты, поэтому в NTFS не может быть атрибутов слишком большой для системы длины.

Очень большие файлы (huge). Если файл настолько велик, что его атрибут дан­ных, хранящий адреса нерезидентных отрезков данных, не помещается в одной записи, то этот атрибут помещается в другую запись MFT, а ссылка на такой ат­рибут помещается в основную запись файла (рис. 7.22). Эта ссылка содержится в атрибуте Attribute List. Сам атрибут данных по-прежнему содержит адреса нерезидейтных отрезков данных.

 

                                              

 

 

 

 

Каталоги NTFS

 

Каждый каталог NTFS представляет собой один вход в таблицу MFT, который содержит атрибут Index Root. Индекс содержит список файлов, входящих в ката­лог. Индексы позволяют сортировать файлы для ускорения поиска, основанного на значении определенного атрибута. Обычно в файловых системах файлы сор­тируются по имени. NTFS позволяет использовать для сортировки любой атри­бут, если он хранится в резидентной форме.

Имеются две формы хранения списка файлов.

Небольшие каталоги (small indexes). Если количество файлов в каталоге невели­ко, то список файлов может быть резидентным в записи в MFT, являющейся ка­талогом (рис. 7.24). Для резидентного хранения списка используется единствен­ный атрибут — Index Root. Список файлов содержит значения атрибутов файла. По умолчанию — это имя файла? а также номер записи MTF, содержащей на­чальную запись файла.

 

Большие каталоги (large indexes). По мере того как каталог растет, список фай­лов может потребовать нерезидентной формы хранения. Однако начальная часть списка всегда остается резидентной в корневой записи каталога в таблице MFT (рис. 7.25). Имена файлов резидентной части списка файлов являются узлами так называемого В-дерева (двоичного дерева). Остальные части списка файлов размещаются вне MFT. Для их поиска используется специальный атрибут Index Allocation, представляющий собой адреса отрезков, хранящих остальные части спи­ска файлов каталога. Одни части списков являются листьями дерева, а другие являются промежуточными узлами, то есть содержат наряду с именами файлов атрибут Index Allocation, указывающий на списки файлов более низких уровней.

Узлы двоичного дерева делят весь список файлов на несколько групп. Имя каж­дого файла-узла является именем последнего файла в соответствующей группе. Считается, что имена файлов сравниваются лексикографически, то есть сначала принимаются во внимание коды первых символов двух сравниваемых имен, при этом имя считается меньшим, если код его первого символа имеет меньшее арифметическое значение, при равенстве кодов первых символов сравниваются коды вторых символов имен и т. д. Например, файл f 1 .ехе, являющийся первым узлом двоичного дерева, показанного на рис. 7.25, имеет имя, лексикографиче­ски большее имен avia.exe, az.exe,..., emax.exe, образующих первую группу спис­ка имен каталога. Соответственно файл ltr.exe имеет наибольшее имя среди всех имен второй группы, а все файлы с именами, большими ltr.exe, образуют третью и последнюю группу.

Поиск в каталоге уникального имени файла, которым в NTFS является номер основной записи о файле в MFT, по его символьному имени происходит следую­щим образом. Сначала искомое символьное имя сравнивается с именем первого узла в резидентной части индекса. Если искомое имя меньше, то это означает, что его нужно искать в первой нерезидентной группе, для чего из атрибута Index Allocation извлекается адрес отрезка (VCN LCN], Kt) хранящего имена файлов первой группы. Среди имен этой группы поиск осуществляется прямым перебором имен и сравнением до полного совпадения всех символов искомого имени с хранящимся в каталоге именем. При совпадении из каталога извлекается номер основной записи о файле в MFT и остальные характеристики файла берутся уже оттуда.

 

 

 

Если же искомое имя больше имени первого узла резидентной части индекса, то его сравнивают с именем второго узла, и если искомое имя меньше, то описанная процедура применяется ко второй нерезидентной группе имен, и т. д.

В результате вместо перебора большого количества имен (в худшем случае — всех имен каталога) выполняется сравнение с гораздо меньшим количеством имен узлов и имен в одной из групп каталога.

Если одна из групп каталога становится слишком большой, то ее также делят на группы, последние имена каждой новой группы оставляют в исходном нерези­дентном атрибуте Index Root, а все остальные имена новых групп переносят в но­вые нерезидентные атрибуты типа Index Root (на рисунке этот случай не показан). К исходному нерезидентному атрибуту Index Root добавляется атрибут размеще­ния индекса, указывающий на отрезки индекса новых групп. Если теперь при поиске искомого имени в нерезидентной части индекса первого уровня какое-либо сравнение показывает, что искомое имя оказывается меньше, чем одно из хранящихся там имен, то это говорит о том, что в данном атрибуте точного срав­нения имени уже быть не может и нужно перейти к подгруппе имен следующего уровня дерева.

 

Файловые операции

 

Два способа организации файловых операций

 

Файловая система ОС должна предоставлять пользователям набор операций ра­боты с файлами, оформленный в виде системных вызовов. Этот набор обычно состоит из таких системных вызовов, как creat (создать файл), read (читать из файла), write (записать в файл) и некоторых других.

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

Какие бы операции не выполнялись над файлом, ОС необходимо выполнить ряд универсальных для всех операций действий:

1.   По символьному имени файла найти его характеристики, которые хранятся в файловой системе на диске.

2.   Скопировать характеристики файла в оперативную память, так как только та­ким образом программный код может их использовать.

3.   На основании характеристик файла проверить права пользователя на выпол­нение запрошенной операции (чтение, запись, удаление, просмотр атрибутов файла).

4.   Очистить область памяти, отведенную под временное хранение характери­стик файла.

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

Операционная система может выполнять последовательность действий над фай­лом двумя способами (рис. 7.26):

□   Для каждой операции выполняются как универсальные, так и уникальные действия. Такая схема иногда называется схемой без запоминания состояния операций {stateless).

□   Все универсальные действия выполняются в начале и конце последователь­ности операций, а для каждой промежуточной операции выполняются только уникальные действия.

Подавляющее большинство файловых систем поддерживает второй способ органи­зации файловых операций как более экономичный и быстрый. Первый способ обладает одним преимуществом — он более устойчив к сбоям в работе системы, так как каждая операция является само достаточной и не зависит от результата предыдущей. Поэтому первый способ иногда применяется в распределенных се­тевых файловых системах (например, в Network File System, NFS компании

Sun), когда сбои из-за потерь пакетов или отказов одного из сетевых узлов более вероятны, чем при локальном доступе к файлам.

 

 

При втором способе в файловой системе вводятся два специальных системных вызова: open — открытие файла, и close — закрытие файла.

Системный вызов открытия файла open выполняется перед началом любой по­следовательности операций с файлом, а вызов закрытия файла close — после окончания работы с файлом. Основной задачей вызова open является преобразо­вание символьного имени файла в его уникальное числовое имя, копирование характеристик файла из дисковой области в буфер оперативной памяти и про­верка прав пользователя на выполнение запрошенной операции. Вызов close ос­вобождает буфер с характеристиками файла и делает невозможным продолже­ние операций с файлом без его повторного открытия.

Операции открытия и закрытия файла в той или иной форме утвердились в опе­рационных системах очень давно. Даже в такой «старой» операционной системе, как OS/360, существовала макрокоманда OPEN, по которой в специальном буфере, называемом DCB (Data Control Block), собирались из различных источников все нужные характеристики набора данных (понятие, близкое к современному поня­тию файла), используемые затем при выполнении операций чтения и записи.

Далее основные системные вызовы файловых операций рассматриваются более детально на примере их реализации в ОС UNIX, в которой они приобрели тот вид, который сегодня поддерживается практически всеми операционными систе­мами.

 

Открытие файла

 

Системный вызов орел в ОС UNIX работает с двумя аргументами: символьным именем открываемого файла и режимом открытия файла. Режим открытия гово­рит системе, какие операции будут выполняться над файлом в последовательно­сти операций до закрытия файла по системному вызову close, например: только чтение, только запись или чтение и запись.

При открытии файла ОС сначала выполняет преобразование первого аргумен­та системного вызова, то есть символьного имени файла, в его уникальное чи­словое имя, которым в традиционных файловых системах UNIX является номер индексного дескриптора. Эта процедура была рассмотрена выше при описании файловой системы s5.

По номеру индексного дескриптора inode файловая система находит нужную запись на диске и копирует из нее характеристики файла в оперативную память.

Для хранения копии индексного дескриптора используются буферные области сис­темного виртуального пространства. Характеристики индексного дескриптора, пере­несенные в оперативную память, помещаются в структуру так называемого виртуаль­ного дескриптора vnode (virtual node). Структура vnode включает поля индексного дескриптора файла inode, а также несколько перечисленных ниже дополнительных полей, полезных при выполнении операций с файлом.

□   Состояние индексного дескриптора в памяти, отражающее: О заблокирован ли файл;

О ждет ли снятия блокировки с файла какой-либо процесс;

О отличается ли представление характеристик файла в памяти от своей дис­ковой копии в результате изменения содержимого индексного дескриптора;

О отличается ли представление файла в памяти от своей дисковой копии в результате изменения содержимого файла;

О является ли файл точкой монтирования.

□   Логический номер устройства файловой системы, содержащей файл.

□   Номер индексного дескриптора. В дисковом индексном дескрипторе это поле отсутствует, так как номер определяется положением дескриптора относитель­но начала области индексных дескрипторов.

□   Счетчик ссылок на данную структуру vnode.

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

Использование единственной копии характеристик файла и некоторых характе­ристик файловых операций (например, признака блокировки), общих для всех работающих с файлом процессов, экономит системную память. Тем не менее существуют характеристики, индивидуальные для каждого процесса, выполняю­щего некоторую последовательность операций с определенным файлом. Для их хранения в UNIX используется структура типа f i I e, которая так же, как и vnode, хранится в системной области памяти.

При каждом открытии процессом файла ОС проверяет права пользовательского процесса на выполнение запрошенной операции с файлом и, если проверка про­шла успешно, создает в системной области памяти новую структуру f i I e, кото­рая описывает как открытый файл, так и операции, которые процесс собирается производить с файлом (например, чтение).

Структура f i 1 e содержит такие поля, как:

□  признак режима открытия (только для чтения, для чтения и записи и т. п.);

□  указатель на структуру vnode;

□  текущее смещение в файле (переменная offset) при операциях чтения/записи;

□  счетчик ссылок на данную структуру;

□  указатель на структуру, содержащую права процесса, открывшего файл (эта структура находится в дескрипторе процесса);

□  указатели на предыдущую и последующую структуры file, связывающие все такие структуры в двойной список.

Переменная offset, хранящаяся в структуре file, позволяет ОС запоминать те­кущее положение условного указателя в последовательности байт файла. При открытии файла эта переменная указывает на начальный или конечный байт фай­ла в зависимости от заданного режима открытия. После выполнения операций чтения или записи указатель сдвигается на то количество байт, которое было прочитано или записано в результате операции. Следующая операция застает указатель в том состоянии, в котором его оставила предыдущая операция. При­кладной программист может явно управлять положением указателя с помощью системного вызова 1 seek, который будет рассмотрен ниже.

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

После создания структуры f i I e операционная система помещает указатель на нее в таблицу открытых файлов процесса, которая находится в контексте процесса. Если процесс несколько раз открывает один и тот же файл, то структура file создается для каждой операции открытия. Так как контекст процесса-родителя в UNIX наследуется процессом-потомком, то потомок наследует и указатели на все открытые родителем файлы, получая возможность выполнять над ними операции.

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

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

Для открытия файла /bin/prog1.exe в режиме «только для чтения» прикладной программист может использовать следующее выражение на языке С:

 fd = ореn("/bin/progl.exe". 0_RDONLY); 

Здесь fd — это целочисленная переменная, сохраняющая значение дескриптора открытого файла. Ее значение должно использоваться в операциях обмена данными с файлом /bin/prog 1 .ехе. При неудачной попытке открытия файла (нет прав  для выполнения затребованной операции, неверное имя файла) переменной fd    присваивается значение -1, которое является индикатором ошибки для всех системных вызовов UNIX.

 

 

Обмен данными с файлом

 

Для обмена данными с предварительно открытым файлом в ОС UNIX существу­ют системные вызовы read и write. В том случае, когда необходимо явным образом указать, с какого байта файла необходимо читать или записывать данные, используется также системный вызов 1 seek.

Системный вызов чтения данных из файла read имеет три аргумента:

 

read(fd,buffer,nbytes);

 

Первый аргумент fd является целочисленной переменной, имеющей значение дескриптора открытого файла. Второй аргумент buffer является указателем на область пользовательской памяти, в которую система должна поместить считан­ные данные. Количество байт этой области памяти задается третьим целочис­ленным аргументом nbytes. Функция read возвращает действительное количест­во считанных байт (оно может отличаться от заданного, если, например, была задана область чтения, выходящая за пределы файла) или же код ошибки -1.

Начало дисковой области, которую нужно прочитать с помощью вызова read, явно в этом системном вызове не указывается. Чтение начинается с того байта, на ко­торый указывает смещение offset в структуре file. На это смещение указывает запись с номером fd в таблице открытых файлов процесса. После выполнения вызова read смещение offset наращивается на количество прочитанных байт.

Вид системного вызова записи данных write аналогичен вызову read:

 

write(fd.buffer.nbytes);

 

Функция write записывает nbytes из буфера оперативной памяти buffer в файл, описываемый дескриптором fd. Функция write, так же как и read, возвращает вы­звавшей ее программе значение реально переданных ею байт или код ошибки. Рассмотрим пример, в котором прикладная программа работает с файлом, со­стоящем из записей фиксированной длины в 50 байт:

 

fd = open('doc/qwery/basel2.txt". 0_RDWR);

read(fd,bufferl.5O);

read(fd.buffer2.2500):

...

lseek(fd.150.0);

write (fd.output. 300):                               .      .                                                         ,

close(fd):

 

В приведенном фрагменте программы после открытия файла /doc/query/base12.txt для чтения и записи выполняется чтение первой записи файла, а затем читается область файла, включающая еще 50 записей, начиная со 2 по 51. После обработ­ки считанных записей (эти инструкции опущены) производятся перемещение указателя смещения в файле на начало четвертой записи и запись результатов в шесть последовательных записей, начиная с четвертой. Завершается фрагмент закрытием файла с помощью системного вызова close.

Все описанные системные вызовы являются синхронными, то есть пользова­тельский процесс переводится в состояние ожидания до тех пор, пока операция ввода-вывода не завершится.

Описанный набор системных вызовов, появившийся в ОС UNIX еще в 70-х го­дах., стал стандартом де-факто для современных операционных систем. Эти тра­диционные системные вызовы часто в конкретных ОС дополняются оригиналь­ными системными вызовами ввода-вывода, например операциями асинхронного типа. На основе системных вызовов ввода-вывода обычно строятся более мощ­ные библиотечные функции ввода-вывода, составляющие прикладной интерфейс ОС.

 

Блокировки файлов  

 

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

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

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

При проверке наличия блокировок, установленных другими процессами, вызов fact немедленно возвращает управление с сообщением результата. При установ­ке блокировки можно задать два режима работы системного вызова: с переходом процесса в состояние ожидания в том случае, если блокировку установить невоз­можно (синхронный системный вызов), и с немедленным возвратом в такой си­туации с сообщением отрицательного результата (асинхронный вызов).

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

В UNIX существуют два режима действия блокировок — консультативный (ad­visory) и обязательный (mandatory). Основным рекомендуемым для использова­ния режимом является консультативный. При нем операционная система не за­нимается блокированием операций с файлом, а только устанавливает признаки блокирования областей в структурах file, поддерживающих операции с файла­ми. Кооперирующиеся процессы обязательно должны проверять наличие блоки­ровок на файл, чтобы синхронизировать свою работу. Если же блокировки уста­новлены, но процесс не проверяет их, то операционная система не запрещает доступ процесса к файлу, когда процесс делает системные вызовы read или write.

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

 

Стандартные файлы ввода и вывода, перенаправление вывода

 

В ОС UNIX были введены в свое время такие понятия, как «стандартный файл ввода», «стандартный файл вывода» и «стандартный файл ошибок». Эти три уже открытых файла существуют у любого пользовательского процесса с момен­та его возникновения. Процесс в любое время может организовать ввод данных из стандартного файла ввода, выполнив следующий системный вызов:

 

read (stdio. bufer. nbytes);

 

Здесь stdio — предопределенное имя константы, обозначающей дескриптор стан­дартного файла ввода.

Аналогично, так как stdout — предопределенное имя дескриптора стандартного файла вывода, процесс может вывести данные в стандартный файл вывода, при­менив следующий системный вызов:

write(stout, buffer, nbytes); За стандартным файлом ошибок закреплено имя stderr.

Фактически при создании нового процесса ОС помещает в его таблицу откры­тых файлов три записи: с номером 0 — для стандартного файла ввода (следова­тельно, stdin всегда имеет значение 0), с номером 1 — для стандартного файла вывода (stdout=l), и с номером 2 — для стандартного файла ошибок (stderr=2). Соответственно создаются и три структуры типа f i I e, на которые указывают пер­вые три записи таблицы открытых файлов процесса.

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

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

Наиболее известной программой, широко использующей стандартные файлы вво­да-вывода, является интерпретатор команд, называемый также оболочкой {shell)

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

Стандартные файлы ввода и ввода широко используются не только интерпрета­тором команд, но и самими командами. Многие внутренние и внешние команды устроены так, что они либо читают свои исходные данные из стандартного фай­ла ввода, либо выводят результаты в стандартный файл вывода. Если же коман­да делает то и другое, она называется фильтром.

Рассмотрим несколько примеров команд UNIX, работающих со стандартными файлами ввода и вывода:

   Is dir2.— читает записи каталога dir2 и выводит их в определенном символь­ном формате в стандартный файл вывода;

□  we — фильтр, который читает последовательность байт из стандартного файла ввода, подсчитывает число слов, строк или символов в считанных данных и выводит результат в стандартный файл вывода;

□  who — выводит в стандартный файл информацию о пользователях, работаю­щих в системе.

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

Перенаправление осуществляется с помощью специальных конструкций ко­мандного языка. Для указания интерпретатору о необходимости перенаправить стандартный ввод на файл file используется следующая конструкция:

< file

Для перенаправления стандартного вывода требуется следующая конструкция:

> file

 

Например, показанная ниже командная строка запишет данные о содержимом каталога dir2 в файл a.txt:

 

Is diг2 > a.txt

 

Механизм перенаправления ввода-вывода, введенный ОС UNIX, получил широ­кое распространение в интерпретаторах команд многих операционных систем, например MS-DOS, Windows, OS/2.

 

Контроль доступа к файлам

 

Доступ к файлам как частный случай доступа к

разделяемым ресурсам

 

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

Во всех этих случаях действует общая схема: пользователи пытаются выполнить с разделяемым ресурсом определенные операции, а ОС должна решать, имеют ли пользователи на это право. Пользователи являются субъектами доступа, а разделяемые ресурсы — объектами. Пользователь осуществляет доступ к объек­там операционной системы не непосредственно, а с помощью прикладных про­цессов; которые запускаются от его имени. Для каждого типа объектов сущест­вует набор операций, которые с ними можно выполнять. Например, для файлов это операции чтения, записи, удаления, выполнения; для принтера — перезапуск, очистка очереди документов, приостановка печати документа и т. д. Система контроля доступа ОС должна предоставлять средства для задания прав пользо­вателей по отношению к объектам дифференцированно по операциям, например, пользователю может быть разрешена операция чтения и выполнения файла, а операция удаления — запрещена.

Во многих операционных системах реализованы механизмы, которые позволяют управлять доступом к объектам различного типа с единых позиций. Так, пред­ставление устройств ввода-вывода в виде специальных файлов в операционных системах UNIX является примером такого подхода: в этом случае при доступе к устройствам используются те же атрибуты безопасности и алгоритмы, что и при доступе к обычным файлам и каталогам. Еще дальше продвинулась в этом на­правлении операционная система Windows NT. В ней используется унифици­рованная структура — объект безопасности, — которая создается не только для файлов и внешних устройств, но и для любых разделяемых ресурсов: секций па­мяти, синхронизирующих примитивов типа семафоров и мьютексов и т. п. Это позволяет использовать в Windows NT для контроля доступа к ресурсам любого вида общий модуль ядра — менеджер безопасности.

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

У каждого объекта доступа существует владелец. Владельцем может быть как отдельный пользователь, так и группа пользователей. Владелец объекта имеет право выполнять с ним любые допустимые для данного объекта операции. Во многих операционных системах существует особый пользователь ( superuser, root, administrator), который имеет все права по отношению к любым объектам систе­мы, не обязательно являясь их владельцем. Под таким именем работает админи­стратор системы, которому необходим полный доступ ко всем файлам и устрой­ствам для управления политикой доступа. Различают два основных подхода к определению прав доступа.

□  Избирательный доступ имеет место, когда для каждого объекта сам владелец может определить допустимые операции с объектами. Этот подход называет­ся также произвольным (от discretionary предоставленный на собственное усмотрение) доступом, так как позволяет администратору и владельцам объ­ектов определить права доступа произвольным образом, по их желанию. Ме­жду пользователями и группами пользователей в системах с избирательным доступом нет жестких иерархических взаимоотношений, то есть взаимоотно­шений, которые определены по умолчанию и которые нельзя изменить. Ис­ключение делается только для администратора, по умолчанию наделяемого всеми правами.

□  Мандатный доступ (от mandatory — обязательный, принудительный) — это такой подход к определению прав доступа, при котором система наделяет поль­зователя определенными правами по отношению к каждому разделяемому ресурсу (в данном случае файлу) в зависимости от того, к какой группе поль­зователь отнесен. От имени системы выступает администратор, а владельцы объектов лишены возможности управлять доступом к ним по своему усмот­рению. Все группы пользователей в такой системе образуют строгую иерар­хию, причем каждая группа пользуется всеми правами группы более низкого уровня иерархии, к которым добавляются права данного уровня. Членам ка­кой-либо группы не разрешается предоставлять свои права членам групп бо­лее низких уровней иерархии. Мандатный способ доступа близок к схемам, применяемым для доступа к секретным документам: пользователь может вхо­дить в одну из групп, отличающихся правом на доступ к документам с соот­ветствующим грифом секретности, например «для служебного пользования», «секретно», «совершенно секретно» и «государственная тайна». При этом поль­зователи группы «совершенно секретно» имеют право работать с документа­ми «секретно» и «для служебного пользования», так как эти виды доступа разрешены для более низких в иерархии групп. Однако сами пользователи не распоряжаются правами доступа — этой возможностью наделен только осо­бый чиновник учреждения.

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

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

 

 

 

 

Механизм контроля доступа

 

Каждый пользователь и каждая группа пользователей обычно имеют символьное имя, а также уникальный числовой идентификатор. При выполнении процедуры логического входа в систему пользователь сообщает свое символьное имя и па­роль, а операционная система определяет соответствующие числовые иденти­фикаторы пользователя и групп, в которые он входит. Вся идентификационные данные, в том числе имена и идентификаторы пользователей и групп, пароли пользователей, а также сведения о вхождении пользователя в группы хранятся в специальном файле (файл /etc/passwd в UNIX) или специальной базе данных (в Windows NT).

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

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

□  создание файла;

□  уничтожение файла;

□   открытие файла;

□  закрытие файла;

□  чтение файла;

□  запись в файл;

□  дополнение файла;

□ поиск в файле;

□   получение атрибутов файла;

□  установка новых значений атрибутов;

□   переименование;

□   выполнение файла;

□  чтение каталога;

□  смена владельца;

□   изменение прав доступа.

Набор файловых операций ОС может состоять из большого количества эле­ментарных операций, а может включать всего несколько укрупненных операций. Приведенный выше список является примером первого подхода, который позво­ляет весьма тонко управлять правами доступа пользователей, но создает значи­тельную нагрузку на администратора. Пример укрупненного подхода демонст­рируют операционные системы семейства UNIX, в которых существуют всего три операции с файлами и каталогами: читать (read, г), писать (write, w) и вы­полнить (execute, x). Хотя в UNIX для операций используется всего три назва­ния, в действительности им соответствует гораздо больше операций. Например, содержание операции выполнить зависит от того, к какому объекту она применя­ется. Если операция выполнить файл интуитивно понятна, то операция выпол­нить каталог интерпретируется как поиск в каталоге определенной записи. По­этому администратор UNIX, по сути, располагает большим списком операций, чем это кажется на первый взгляд.

В ОС Windows NT разработчики применили гибкий подход — они реализовали возможность работы с операциями над файлами на двух уровнях: по умолчанию администратор работает на укрупненном уровне (уровень стандартных операций), а при желании может перейти на элементарный уровень (уровень индивидуаль­ных операций).

В самом общем случае права доступа могут быть описаны матрицей прав досту­па, в которой столбцы соответствуют всем файлам системы, строки — всем поль­зователям, а на пересечении строк и столбцов указываются разрешенные опера­ции (рис. 7.28).

 

 

Практически во всех операционных системах матрица прав доступа хранится «по частям», то есть для каждого файла или каталога создается так называемый список управления доступом (Access Control List, ACL), в котором описываются права на выполнение операций пользователей и групп пользователей по отноше­нию к этому файлу или каталогу. Список управления доступа является частью характеристик файла или каталога и хранится на диске в соответствующей об­ласти, например в индексном дескрипторе inode файловой системы ufs. He все файловые системы поддерживают списки управления доступом, например, его не поддерживает файловая система FAT, так как она разрабатывалась для одно­пользовательской однопрограммной операционной системы MS-DOS, для кото­рой задача защиты от несанкционированного доступа не актуальна.

Обобщенно формат списка управления доступом можно представить в виде на­бора идентификаторов пользователей и групп пользователей, в котором для каж­дого идентификатора указывается набор разрешенных операций над объектом (рис. 7.29). Говорят, что список ACL состоит из элементов управления доступом (Access Control Element, АСЕ), при этом каждый элемент соответствует одному идентификатору. Список ACL с добавленным к нему идентификатором владель­ца называют характеристиками безопасности.

 

В приведенном на рисунке примере процесс, который выступает от имени поль­зователя с идентификатором 3 и групп с идентификаторами 14, 52 и 72, пытается выполнить операцию записи (W) в файл. Файлом владеет пользователь с идентификатором 17. Операционная система, получив запрос на запись, находит характеристики безопасности файла (на диске или в буферной системной облас­ти) и последовательно сравнивает все идентификаторы процесса с идентифика­тором владельца файла и идентификаторами пользователей и групп в элементах АСЕ. В данном примере один из идентификаторов группы, от имени которой выступает процесс, а именно 52, совпадает с идентификатором одного из элемен­тов АСЕ. Так как пользователю с идентификатором 52 разрешена операция чте­ния (признак W имеется в наборе операций этого элемента), то ОС разрешает процессу выполнение операции.

Описанная обобщенная схема хранения информации о правах доступа и проце­дуры проверки имеет в каждой операционной системе свои особенности, ко­торые рассматриваются далее на примере операционных систем UNIX и Win­dows NT.

 

Организация контроля доступа в ОС UNIX

 

В ОС UNIX права доступа к файлу или каталогу определяются для трех субъек­тов:

□   владельца файла (идентификатор User ID, UID);

□  членов группы, к которой принадлежит владелец (Group ID, GID);

□ всех остальных пользователей системы.

С учетом того что в UNIX определены всего три операции над файлами и ката­логами (чтение, запись, выполнение), характеристики безопасности файла вклю­чают девять признаков, задающих возможность выполнения каждой из трех операций для каждого из трех субъектов доступа. Например, если владелец фай­ла разрешил себе выполнение всех трех операций, для членов группы — чтение и выполнение, а для всех остальных пользователей — только выполнение, то де­вять характеристик безопасности файла выглядят следующим образом:

 

rwx r-х г--

 

Здесь г, w и х обозначают операции чтения, записи и выполнения соответственно. Именно в таком виде выводит информацию о правах доступа к файлам команда просмотра содержимого каталога 1 s. Суперпользователю UNIX все виды досту­па позволены всегда, поэтому его идентификатор (он имеет значение 0) не фигу­рирует в списках управления доступом.

С каждым процессом UNIX связаны два идентификатора: пользователя, от име­ни которого был создан этот процесс, и группы, к которой принадлежит данный пользователь. Эти идентификаторы носят название реальных идентификаторов пользователя: Real User ID, RUID и реальных идентификаторов группы: Real Group ID, RGID. Однако при проверке прав доступа к файлу используются не эти идентификаторы, а так называемые эффективные идентификаторы пользо­вателя: Effective User ID, EUID и эффективные идентификаторы группы: Effec­tive Group ID, EGID (рис. 7.30).

 

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

Случаи, когда процесс выполняет системный вызов exec запуска приложения, хра­нящегося в некотором файле, в UNIX связаны со сменой процессом исполняемо­го кода. В рамках данного процесса начинает выполняться новый код, и если в характеристиках безопасности этого файла указаны признаки разрешения смены идентификаторов пользователя и группы, то происходит смена эффективных иден­тификаторов процесса. Файл имеет два признака разрешения смены идентифи­катора — Set User ID on execution (SUID) и Set Group ID on execution (SGID), которые разрешают смену идентификаторов пользователя и группы при выпол­нении данного файла.

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

Первоначально процесс А имел эффективные идентификаторы пользователя и группы (12 и 23 соответственно), совпадающие с реальными. На каком-то этапе работы процесс запросил выполнение приложения из файла b.ехе. Процесс мо­жет выполнить файл b.ехе, хотя его эффективные идентификаторы не совпада­ют с идентификатором владельца и группы файла, так как выполнение разреше­но всем пользователям.

 

Файл b.ехе имеет установленные признаки смены идентификаторов SUID и SGID, поэтому одновременно со сменой кода процесс меняет и значения эффективных идентификаторов (35 и 47). Вследствие этого при последующей попытке запи­сать данные в файл f 1 .doc процессу А это удается, так как его новый эффектив­ный идентификатор группы совпадает с идентификатором группы файла f 1 .doc. Без смены идентификаторов эта операция для процесса А была бы запрещена.

Описанный механизм преследует те же цели, что и рассмотренный выше меха­низм подчиненных сегментов процессора Pentium.

Использование модели файла как универсальной модели разделяемого ресурса позволяет в UNIX применять одни и те же механизмы для контроля доступа к файлам, каталогам, принтерам, терминалам и разделяемым сегментам памяти.

Система управления доступом ОС UNIX была разработана в 70-е годы и с тех пор мало изменилась. Эта достаточно простая система позволяет во многих слу­чаях решить поставленные перед администратором задачи по предотвращению несанкционированного доступа, однако такое решение иногда требует слишком больших ухищрений или же вовсе не может быть реализовано.

 

Организация контроля доступа в ОС Windows NT

 

Общая характеристика

 

Система управления доступом в ОС Windows NT отличается высокой степенью гибкости, которая достигается за счет большого разнообразия субъектов и объ­ектов доступа, а также детализации операций доступа.

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

Все объекты хранятся в древовидных иерархических структурах, элементами ко­торых являются объекты-ветви (каталоги) и объекты-листья (файлы). Для объ­ектов файловой системы такая схема отношений является прямым отражением иерархии каталогов и файлов. Для объектов других типов иерархическая схема отношений имеет свое содержание, например, для процессов она отражает связи «родитель-потомок», а для устройств отражает принадлежность к определенно­му типу устройств и связи устройства с другими устройствами, например SCSI-контроллера с дисками.

Проверка прав доступа для объектов любого типа выполняется централизованно с помощью монитора безопасности (Security Reference Monitor), работающего в привилегированном режиме. Централизация функций контроля доступа повы­шает надежность средств защиты информации операционной системы по срав­нению с распределенной реализацией, когда в различных модулях ОС имеются свои процедуры проверки прав доступа и вероятность ошибки программиста от этого возрастает.

Для системы безопасности Windows NT характерно наличие большого количест­ва различных предопределенных (встроенных) субъектов доступа — как отдель­ных пользователей, так и групп. Так, в системе всегда имеются такие пользовате­ли, как Administrator, System и Guest, а также группы Users, Administrators, Account Operators, Server Operators, Everyone и другие. Смысл этих встроенных пользо­вателей и групп состоит в том, что они наделены некоторыми правами, облегчая администратору работу по созданию эффективной системы разграничения до­ступа. При добавлении нового пользователя администратору остается только решить, к какой группе или группам отнести этого пользователя. Конечно, адми­нистратор может создавать новые группы, а также добавлять права к встроен­ным группам для реализации собственной политики безопасности, но во многих случаях встроенных групп оказывается вполне достаточно. Windows NT поддерживает три класса операций доступа, которые отличаются типом субъектов и объектов, участвующих в этих операциях.

□  Разрешения (permissions) — это множество операций, которые могут быть определены для субъектов всех типов по отнощению к объектам любого типа: файлам, каталогам, принтерам, секциям памяти и т. д. Разрешения по своему назначению соответствуют правам доступа к файлам и каталогам в ОС UNIX.

□   Права (user rights) — определяются для субъектов типа группа на выполнение некоторых системных операций: установку системного времени, архивирова­ние файлов, выключение компьютера и т. п. В этих операциях участвует осо­бый объект доступа — операционная система в целом. В основном именно права, а не разрешения отличают одну встроенную группу пользователей от другой. Некоторые права у встроенной группы являются также встроенны­ми — их у данной группы нельзя удалить. Остальные права встроенной груп­пы можно удалять (или добавлять из общего списка прав).

□ Возможности пользователей (user abilities) определяются для отдельных пользо­вателей на выполнение действий, связанных с формированием их операци­онной среды, например изменение состава главного меню программ, возмож­ность пользоваться пунктом меню Run (выполнить) и т. п. За счет уменьшения набора возможностей (которые по умолчанию доступны пользователю) адми­нистратор может «заставить» пользователя работать с той операционной сре­дой, которую администратор считает наиболее подходящей и ограждающей ,  пользователя от возможных ошибок.

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

Проверка разрешений доступа процесса к объекту производится в Windows NT в основном в соответствии с общей схемой доступа, представленной на рис. 7.29.

При входе пользователя в систему для него создается так называемый токен доступа (access token), включающий идентификатор пользователя и идентифи­каторы всех групп, в которые входит пользователь. В токене также имеются: спи­сок управления доступом (ACL) по умолчанию, который состоит из разрешений и применяется к создаваемым процессом объектам; список прав пользователя на выполнение системных действий.

Все объекты, включая файлы, потоки, события, даже токены доступа, когда они создаются, снабжаются дескриптором безопасности. Дескриптор безопасности содержит список управления доступом — ACL. Владелец объекта, обычно поль­зователь, который его создал, обладает правом избирательного управления досту­пом к объекту и может изменять ACL объекта, чтобы позволить или не позволить другим осуществлять доступ к объекту. Встроенный администратор Windows NT в отличие от суперпользователя UNIX может не иметь некоторых разрешений на доступ к объекту. Для реализации этой возможности идентификаторы адми­нистратора и группы администраторов могут входить в ACL, как и идентифи­каторы рядовых пользователей. Однако администратор все же имеет возмож­ность выполнить любые операции с любыми объектами, так как он всегда может стать владельцем объекта, а затем уже как владелец получить полный набор раз­решений. Однако вернуть владение предыдущему владельцу объекта админист­ратор не может, поэтому пользователь всегда может узнать о том, что с его фай­лом или принтером работал администратор.

При запросе процессом некоторой операции доступа к объекту в Windows NT управление всегда передается монитору безопасности, который сравнивает иден­тификаторы пользователя и групп пользователей из токена доступа с иденти­фикаторами, хранящимися в элементах ACL объекта. В отличие от UNIX в эле­ментах ACL Windows NT могут существовать как списки разрешенных, так и списки, запрещенных для пользователя операций.

Система безопасности могла бы осуществлять проверку разрешений каждый раз, когда процесс использует объект. Но список ACL состоит из многих элементов, процесс в течение своего существования может иметь доступ ко многим объек­там, и количество активных процессов в каждый момент времени также велико. Поэтому проверка выполняется только при каждом открытии, а не при каждом использовании объекта.

Для смены в некоторых ситуациях процессом своих идентификаторов в Win­dows NT используется механизм олицетворения (impersonation). В Windows NT существуют простые субъекты и субъекты-серверы. Простой субъект — это про­цесс, которому не разрешается смена токена доступа и соответственно смена иден­тификаторов. Субъект-сервер — это процесс, который работает в качестве сервера и обслуживает процессы своих клиентов (например, процесс файлового серве­ра). Поэтому такому процессу разрешается получить токен доступа у процесса-клиента, запросившего у сервера выполнения некоторого действия, и использо­вать его при доступе к объектам.

В Windows NT однозначно определены правила, по которым вновь создаваемо­му объекту назначается список ACL. Если вызывающий код во время создания объекта явно задает все права доступа к вновь создаваемому объекту, то система безопасности приписывает этот ACL объекту.

Если же вызывающий код не снабжает объект списком ACL, а объект имеет имя, то применяется принцип наследования разрешений. Система безопасности про­сматривает ACL того каталога объектов, в котором хранится имя нового объекта. Некоторые из входов ACL каталога объектов могут быть помечены как насле­дуемые. Это означает, что они могут быть приписаны новым объектам, создавае­мым в этом каталоге.            

В том случае, когда процесс не задал явно список ACL для создаваемого объекта и объект-каталог не имеет наследуемых элементов ACL, используется список ACL по умолчанию из токена доступа процесса.

Наследование разрешений употребляется наиболее часто при создании нового объекта. Особенно оно эффективно при создании файлов, так как эта операция выполняется в системе наиболее часто.

 

Разрешения на доступ к каталогам и файлам

 

В Windows NT администратор может управлять доступом пользователей к ката­логам и файлам только в разделах диска, в которых установлена файловая систе­ма NTFS. Разделы FAT не поддерживаются средствами защиты Windows NT, так как в FAT у файлов и каталогов отсутствуют атрибуты для хранения спи­сков управления доступом. Доступ к каталогам и файлам контролируется за счет установки соответствующих разрешений.

Разрешения в Windows NT бывают индивидуальные и стандартные. Индиви­дуальные разрешения относятся к элементарным операциям над каталогами и файлами, а стандартные разрешения являются объединением нескольких инди­видуальных разрешений.

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

 

 

Разрешение Full Control отличается от Change тем, что дает право на измене­ние разрешений (Change Permission) и вступление во владение файлом (Take Ownership).

Для каталогов в Windows NT определено семь стандартных разрешений: No Access, List, Read, Add, Add&Read, Change и Full Control. В следующей таблице показано соответствие стандартных разрешений индивидуальным разрешениям для каталогов, а также то, каким образом эти стандартные разрешения преобра­зуются в индивидуальные разрешения для файлов, входящих в каталог в том случае, если файлы наследуют разрешения каталога.

 

 

При создании файла он наследует разрешения от каталога указанным способом только в том случае, если у каталога установлен признак наследования его раз­решений. Стандартная оболочка Windows NTWindows Explorer — не позво­ляет установить такой признак для каждого разрешения отдельно (то есть задать маску наследования), управляя наследованием по принципу «все или ничего».

Существует ряд правил, которые определяют действие разрешений.

□   Пользователи не могут работать с каталогом или файлом, если они не имеют явного разрешения на это или же они не относятся к группе, которая имеет соответствующее разрешение.

□   Разрешения имеют накопительный эффект, за исключением разрешения No Access, которое отменяет все остальные имеющиеся разрешения. Например, если группа Engineering имеет разрешение Change для какого-то файла, а группа Finance имеет для этого файла только разрешение Read и Петров яв­ляется членом обеих групп, то у Петрова будет разрешение Change. Однако если разрешение для группы Finance изменится на No Access, то Петров не сможет использовать этот файл, несмотря на то что он член группы, которая имеет доступ к файлу.

По умолчанию в окнах Windows Explorer находят свое отражение стандартные права, а переход к отражению индивидуальных прав происходит только при вы­полнении некоторых действий. Это стимулирует администратора и пользовате­лей к использованию тех наборов прав, которые разработчики ОС посчитали наиболее удобными.

 

Встроенные группы пользователей и их права

 

Мощность и гибкость системы безопасности Windows NT во многом определя­ется наличием в ней достаточно широкого набора прав групп пользователей на выполнение системных действий. Для иллюстрации этого утверждения в сле­дующих двух таблицах приводятся списки изменяемых и встроенных прав для встроенных групп Windows NT.

Первой показана таблица изменяемых прав встроенных групп. В следующей таблице представлены встроенные права встроенных групп.