файла, она увеличивает значение счетчика в соответствующей записи таблицы файлов — записи, на которую указывают связанные с ней точки входа в таблице файловых дескрипторов, которых теперь стало на одну больше. Например, обзор структур данных, изображенных на Рисунке 5.20, показывает, что процесс вызывает следующую последовательность функций: он открывает (open) файл с именем «/etc/passwd» (файловый дескриптор 3), затем открывает файл с именем «local» (файловый дескриптор 4), снова файл с именем «/etc/passwd» (файловый дескриптор 5) и, наконец, дублирует (dup) файловый дескриптор 3, возвращая дескриптор 6.

Рисунок 5.20. Структуры данных после выполнения функции dup

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

Рассмотрим программу, приведенную на Рисунке 5.21. В переменной i хранится дескриптор файла, возвращаемый в результате открытия файла «/etc/passwd», а в переменной j — дескриптор файла, возвращаемый системой в результате дублирования дескриптора i с помощью функции dup. В адресном пространстве процесса оба пользовательских дескриптора, представленные переменными i и j, ссылаются на одну и ту же запись в таблице файлов и поэтому используют одно и то же значение смещения внутри файла. Таким образом, первые два вызова процессом функции read реализуют последовательное считывание данных, и в буферах buf1 и buf2 будут располагаться разные данные. Совсем другой результат получается, когда процесс открывает один и тот же файл дважды и читает дважды одни и те же данные (раздел 5.2). Процесс может освободить с помощью функции close любой из файловых дескрипторов по своему желанию, и ввод-вывод получит нормальное продолжение по другому дескриптору, как показано на примере. В частности, процесс может «закрыть» дескриптор файла стандартного вывода (файловый дескриптор 1), снять с него копию, имеющую то же значение, и затем рассматривать новый файл в качестве файла стандартного вывода. В главе 7 будет представлен более реалистический пример использования функций pipe и dup при описании особенностей реализации командного процессора.

#include ‹fcntl.h›

main() {

 int i, j;

 char buf1[512], buf2[512];

 i = open('/etc/passwd', O_RDONLY);

 j = dup(i);

 read(i, buf1, sizeof(buf1));

 read(j, buf2, sizeof(buf2));

 close(i);

 read(j, buf2, sizeof(buf2));

}

Рисунок 5.21. Программа на языке Си, иллюстрирующая использование функции dup

5.14 МОНТИРОВАНИЕ И ДЕМОНТИРОВАНИЕ ФАЙЛОВЫХ СИСТЕМ

Физический диск состоит из нескольких логических разделов, на которые он разбит дисковым драйвером, причем каждому разделу соответствует файл устройства, имеющий определенное имя. Процессы обращаются к данным раздела, открывая соответствующий файл устройства и затем ведя запись и чтение из этого «файла», представляя его себе в виде последовательности дисковых блоков. Это взаимодействие во всех деталях рассматривается в главе 10. Раздел диска может содержать логическую файловую систему, состоящую из блока начальной загрузки, суперблока, списка индексов и информационных блоков (см. главу 2). Системная функция mount (монтировать) связывает файловую систему из указанного раздела на диске с существующей иерархией файловых систем, а функция umount (демонтировать) выключает файловую систему из иерархии. Функция mount, таким образом, дает пользователям возможность обращаться к данным в дисковом разделе как к файловой системе, а не как к последовательности дисковых блоков.

Синтаксис вызова функции mount:

mount(special pathname, directory pathname, options);

где special pathname — имя специального файла устройства, соответствующего дисковому разделу с монтируемой файловой системой, directory pathname — каталог в существующей иерархии, где будет монтироваться файловая система (другими словами, точка или место монтирования), а options указывает, следует ли монтировать файловую систему «только для чтения» (при этом не будут выполняться такие функции, как write и creat, которые производят запись в файловую систему). Например, если процесс вызывает функцию mount следующим образом:

mount('/dev/dsk1', '/usr', 0);

ядро присоединяет файловую систему, находящуюся в дисковом разделе с именем «/dev/dsk1», к каталогу «/usr» в существующем дереве файловых систем (см. Рисунок 5.22). Файл «/dev/dsk1» является блочным специальным файлом, т. е. он носит имя устройства блочного типа, обычно имя раздела на диске. Ядро предполагает, что раздел на диске с указанным именем содержит файловую систему с суперблоком, списком индексов и корневым индексом. После выполнения функции mount к корню смонтированной файловой системы можно обращаться по имени «/usr». Процессы могут обращаться к файлам в монтированной файловой системе и игнорировать тот факт, что система может отсоединяться. Только системная функция link контролирует файловую систему, так как в версии V не разрешаются связи между файлами, принадлежащими разным файловым системам (см. раздел 5.15).

Рисунок 5.22. Дерево файловых систем до и после выполнения функции mount

Ядро поддерживает таблицу монтирования с записями о каждой монтированной файловой системе. В каждой записи таблицы монтирования содержатся:

• номер устройства, идентифицирующий монтированную файловую систему (упомянутый выше логический номер файловой системы);

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

• указатель на корневой индекс монтированной файловой системы («/» для файловой системы с именем «/dev/dsk1» на Рисунке 5.22);

• указатель на индекс каталога, ставшего точкой монтирования (на Рисунке 5.22 это каталог «usr», принадлежащий корневой файловой системе).

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

алгоритм mount

входная информация:

 имя блочного специального файла

 имя каталога точки монтирования

 опции («только для чтения»)

выходная информация: отсутствует

{

 if (пользователь не является суперпользователем) return (ошибку);

 получить индекс для блочного специального файла (алгоритм namei);

 проверить допустимость значений параметров;

 получить индекс для имени каталога, где производится монтирование (алгоритм namei);

 if (индекс не является индексом каталога или счетчик ссылок имеет значение › 1) {

  освободить индексы (алгоритм iput);

  return (ошибку);

 }

 найти свободное место в таблице монтирования;

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

 получить свободный буфер из буферного кеша;

 считать суперблок в свободный буфер;

 проинициализировать поля суперблока;

 получить корневой индекс монтируемой системы (алгоритм iget), сохранить его в таблице монтирования;

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

 освободить индекс специального файла (алгоритм iput);

 снять блокировку с индекса каталога точки монтирования;

Добавить отзыв
ВСЕ ОТЗЫВЫ О КНИГЕ В ИЗБРАННОЕ

0

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

Отметить Добавить цитату