Файл: Debian Таненбаум Бос.pdf

ВУЗ: Не указан

Категория: Книга

Дисциплина: Операционные системы

Добавлен: 29.10.2018

Просмотров: 48072

Скачиваний: 190

ВНИМАНИЕ! Если данный файл нарушает Ваши авторские права, то обязательно сообщите нам.
background image

856  

 Глава 10. Изучение конкретных примеров: Unix, Linux и Android 

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

Группа, к которой принадлежит файл

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

Время создания

Время последнего доступа

Время последней модификации

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

sort <in | head -30

дескриптор файла 1 (стандартный вывод) в процессе, выполняющем программу sort, 
будет настроен оболочкой на запись в канал, а дескриптор файла 0 (стандартный ввод) 
в процессе, выполняющем программу head, будет настроен на чтение из канала. Про-
грамма sort просто читает из файла с дескриптором 0 (установлен на файл 

in

) и пишет 

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

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

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

Таблица 10.11. Некоторые системные вызовы, относящиеся к работе с каталогами. 
В случае ошибки возвращаемое значение s равно –1; dir идентифицирует каталог; 
а dirent представляет собой запись каталога. Параметры должны быть понятны без 
пояснений

Системный вызов

Описание

s=mkdir(path, mode)

Создать новый каталог

s=rmdir(path)

Удалить каталог

s=link(oldpath, newpath)

Создать ссылку на существующий файл

Таблица 10.10 (продолжение)


background image

10.6. Файловая система UNIX   

857

Системный вызов

Описание

s=unlink(path)

Удалить ссылку

s=chdir(path)

Изменить рабочий каталог

dir=opendir(path)

Открыть каталог для чтения

s=closedir(dir)

Закрыть каталог

dirent=readdir(dir)

Прочитать одну запись каталога

rewinddir(dir)

Установить указатель в каталоге на первую запись

Как было показано на рис. 10.14, при создании ссылки на файл создается новая  запись 
в каталоге, указывающая на существующий файл. Ссылка создается при помощи си-
стемного вызова link. В параметрах этого системного вызова указываются исходное 
и новое имя. Записи в каталоге удаляются системным вызовом unlink. Когда удаляется 
последняя ссылка на файл, файл также автоматически удаляется. Если для файла не 
было создано ни одной ссылки, то при первом же обращении к системному вызову 
unlink файл исчезнет.

Рабочий каталог можно изменить при помощи системного вызова chdir. После выпол-
нения этого системного вызова будут по-другому интерпретироваться относительные 
имена путей.

Последние четыре системных вызова в табл. 10.11 предназначены для чтения каталогов. 
Каталоги могут открываться, закрываться и читаться аналогично обычным файлам. 
Каждое обращение к системному вызову readdir возвращает ровно одну запись ката-
лога (в фиксированном формате). Пользователям запрещено писать в каталоги (это 
делается, чтобы пользователи случайно не нарушили целостности системы). Файлы 
могут добавляться к каталогу при помощи системных вызовов creat и link, а удаляться 
с помощью системного вызова unlink. В операционной системе Linux нет способа перей-
ти к конкретному файлу в каталоге, но есть системный вызов rewinddir, позволяющий 
начать читать открытый каталог с начала.

10.6.3. Реализация файловой системы Linux

В этом разделе мы сначала рассмотрим поддерживаемые уровнем виртуальной фай-
ловой системы (Virtual File System (VFS)) абстракции. VFS скрывает (от процессов 
и приложений верхнего уровня) отличия поддерживаемых в Linux файловых систем 
(находятся они на локальных устройствах или удаленно — с доступом по сети). Доступ 
к устройствам и другим специальным файлам также получаем через уровень VFS. За-
тем мы опишем реализацию первой получившей широкое распространение файловой 
системы Linux под названием ext2 (вторая расширенная файловая система). После 
этого обсудим улучшения файловой системы ext4. Используется также множество 
других файловых систем. Все Linux-системы могут работать с большим количеством 
дисковых разделов, причем в каждом может быть своя файловая система.

Виртуальная файловая система Linux

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


background image

858  

 Глава 10. Изучение конкретных примеров: Unix, Linux и Android 

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

В табл. 10.12 даны четыре основные структуры файловой системы, поддерживаемые 
VFS. Суперблок содержит критичную информацию о компоновке файловой системы. 
Разрушение суперблока делает файловую систему нечитаемой. i-узел (сокращение от 
«индекс-узлы», никто их так не называет) описывает один файл. Обратите внимание 
на то, что в Linux каталоги и устройства также представлены файлами, так что они 
тоже имеют соответствующие i-узлы. И суперблок, и i-узлы имеют соответствующие 
структуры на том физическом диске, где находится файловая система.

Таблица 10.12. Поддерживаемые в VFS абстракции файловой системы

Объект

Описание

Операция

Суперблок

Конкретная файловая система

read_inode, sync_fs

Элемент каталога (dentry)

Элемент каталога, компонент пути

create, link

i-узел

Конкретный файл

d_compare, d_delete

Файл (file)

Открыть связанный с процессом файл

read, write

Чтобы улучшить некоторые операции с каталогами и перемещение по путям (таким, 
как 

/usr/ast/bin

), VFS поддерживает структуру данных dentry, которая представляет 

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

/

/usr

/usr/ast

 и т. д. Если несколько процессов обраща-

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

И наконец, структура данных file является представлением открытого файла в памяти, 
она создается в ответ на системный вызов open. Она поддерживает такие операции, 
как readwritesendfilelock (и прочие описанные в предыдущем разделе системные 
вызовы).

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

Файловая система Ext2 в Linux

Теперь мы опишем наиболее популярную дисковую файловую систему Linux — ext2
Первый выпуск Linux использовал файловую систему MINIX 1, которая имела ко-
роткие имена файлов и максимальный размер файла 64 Мбайт. Файловая система 
MINIX 1 была в итоге заменена первой расширенной файловой системой ext, кото-


background image

10.6. Файловая система UNIX   

859

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

Дисковый раздел с ext2 содержит файловую систему с показанной на рис. 10.17 компо-
новкой. Блок 0 не используется системой Linux и содержит код загрузки компьютера. 
Следом за блоком 0 дисковый раздел разделен на группы блоков (без учета границ 
цилиндров диска). Каждая группа организована следующим образом.

Рис. 10.17. Размещение файловой системы ext2 на диске

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

В двух битовых массивах ведется учет свободных блоков и свободных i-узлов (это тоже 
унаследовано из файловой системы MINIX 1 и отличает ее от большинства файловых 
систем UNIX, в которых для свободных блоков используется список). Размер каждого 
битового массива равен одному блоку. При размере блока 1 Кбайт такая схема ограни-
чивает размер группы блоков 8192 блоками и 8192 i-узлами. Первое число является 
реальным ограничением, а второе — практически нет. При блоках размером 4 Кбайт 
числа в четыре раза больше.

Затем располагаются сами i-узлы. Они нумеруются от 1 до некоторого максимума. 
Размер каждого i-узла — 128 байт, и описывает он ровно один файл. i-узел содержит 
учетную информацию (в том числе всю возвращаемую вызовом stat, который просто 
берет ее из i-узла), а также достаточное количество информации для определения ме-
стоположения всех дисковых блоков, которые содержат данные файла.

Следом за i-узлами идут блоки данных. Здесь хранятся все файлы и каталоги. Если 
файл или каталог состоит более чем из одного блока, то эти блоки не обязаны быть не-
прерывными на диске. В действительности блоки большого файла, скорее всего, будут 
разбросаны по всему диску.

Соответствующие каталогам i-узлы разбросаны по всем группам дисковых блоков. 
Ext2 пытается расположить обычные файлы в той же самой группе блоков, что и ро-
дительский каталог, а файлы данных — в том же блоке, что и i-узел исходного файла 
(при условии, что там имеется достаточно места). Эта идея была позаимствована из 
файловой системы Berkeley Fast File System (McKusick et al., 1984). Битовые массивы 
используются для того, чтобы принимать быстрые решения относительно выделения 


background image

860  

 Глава 10. Изучение конкретных примеров: Unix, Linux и Android 

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

Для доступа к файлу нужно сначала использовать один из системных вызовов Linux 
(такой, как open), для которого нужно указать путь к файлу. Этот путь разбирается, 
и из него извлекаются составляющие его каталоги. Если указан относительный путь, 
то поиск начинается с текущего каталога процесса, в противном случае — с корневого 
каталога. В любом случае, i-узел для первого каталога найти легко: в дескрипторе про-
цесса есть указатель на него либо (в случае корневого каталога) он хранится в опреде-
ленном блоке на диске.

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

Рис. 10.18. Каталог Linux: а — с тремя файлами; б — после удаления файла voluminous

Каждая запись каталога на рис. 10.18 состоит из четырех полей фиксированной длины 
и одного поля переменной длины. Первое поле представляет собой номер i-узла, рав-
ный 19 для файла 

colossal

, 42 для файла 

voluminous

 и 88 для каталога 

bigdir

. Следом 

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