Главная страница  Межпроцессное взаимодействие (состязание) 

1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 103 104 105 106 107 108 109 110 111 112 113 114 115 116 117 118 119 120 121 122 123 124 125 126 127 128 129 130 131 132 133 134 135 136 137 138 139 140 141 142 143 144 145 146 147 148 149 150 151 152 153 154 155 156 157 158 159 160 161 162 163 164 165 166 167 168 169 170 171 172 173 174 175 176 [ 177 ] 178 179 180 181 182 183 184 185 186 187

♦ не хватает памяти для суперблока монтируемой файловой системы;

♦ не хватает памяти для корневого г-узла монтируемой файловой системы.

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

Томас Эдисон сделал одно замечание, которое применимо и к нашему случаю. Он сказал, что гений - это 1 % вдохновения и 99 % труда. Различие между хорошей и посредственной системой не в превосходном алгоритме планирования, а в том внимании, которое уделено деталям.

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

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

Создание и уничтожение ссылок

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

link(file name. link name):

♦ файл file name не существует или недоступен;

♦ у файла file name уже есть максимальное количество ссылок;

♦ файл file name является каталогом (создавать такие ссылки имеет право только суперпользователь);

♦ файл link name уже существует;

♦ Link name и file name расположены на разных устройствах.

Если все в порядке, в каталоге создается новая запись с именем link name и номером г-узла file name. В коде имя namel соответствует file name, а пате2 - link name. Вносит новую запись в каталог функция search dir, вызываемая из delink.



Удаление файлов и каталогов происходит путем уничтожения ссылок на них. Поэтому оба системных вызова unlink и rmdir обслуживаются единственной функцией do unlink. Опять же, в ней делается множество различных проверок, общий код убеждается, что файл существует и не является точкой монтирования, после чего, в зависимости от типа вызова, управление передается либо процедуре remove dir, либо unlink file. Мы вскоре обсудим эти две подпрограммы.

Код в файле link.c обеспечивает работу еще одного системного вызова, rename. Пользователям UNIX должна быть знакома команда оболочки mv, которая пользуется исключительно этим вызовом. Ее название отражает еще один из аспектов вызова, так как он способен не только менять имя файла, но и эффективно перемещать его из одного каталога в другой, причем операция перемещения атомарная, что позволяет избежать ситуации состязания. Этот вызов обрабатывается функцией do rename. Перед выполнением команды проверяется множество условий, среди которых есть следующие:

f исходный файл должен существовать;

♦ новый путь не должен быть подкаталогом старого;

♦ новое имя не может быть ни . , ни .. ;

♦ исходный и конечный каталоги должны находиться на одном устройстве;

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

♦ ни старое, ни новое имя не могут обозначать каталог, в который смонтирована файловая система.

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

В коде do rename можно увидеть несколько приемов, служащих для снижения риска некоторых проблем. Если при переименовании файл с новым именем уже существует, то при заполненном диске может произойти ошибка, невзирая на то, что в конечном итоге дополнительное место не используется. Чтобы обойти эту проблему, старый файл сначала удаляется, за это отвечают строки кода с 260 по 266. По тем же соображениям из каталога сначала удаляется старое имя файла (в коде на 280-й строке), а затем в него записывается новое, во избежание выделения для каталога нового блока. Это соображение не применимо к тому случаю, когда новый и старый файлы расположены в разных каталогах, поэтому на 285-й строке, посвященной данной ситуации, сначала создается новое имя, а затем удаляется старое. Такой подход должен уменьшить риск повреждения файловой системы, если произойдет сбой, так как с точки зрения целостности гораздо лучше иметь две ссылки на один г-узел, чем г-узел, на который нет ссылок ни в одном из каталогов. Вероятность, что в процессе переименования кончится свободное место, невысока, а вероятность краха системы еще меньше, но в данном случае ничего не стоит приготовиться к худшему варианту.

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



в коде файловой системы. Она проходит по i-узлу зона за зоной, освобождая все найденные зоны, а также косвенные блоки. Функция remove dir сначала делает ряд проверок, чтобы удостовериться, что каталог можно удалить, а затем вызывает unlink file. Если никаких ошибок не произошло, запись каталога очищается и счетчик в i-узле декрементируется.

5.7.6. Прочие вызовы файловой системы

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

Управление состоянием каталогов и файлов

Файл stadir.c содержит код для четырех системных вызовов: chdir, chroot, stat и fstat. Изучая код last dir, мы видели, что поиск файла по имени начинается с проверки первого символа пути. Если первый символ оказывался слэшем, брался указатель на корневой каталог, если нет - на рабочий.

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

В функции do chdir есть код, не исполняемый пользовательскими процессами (с 35 строки по 51). Он предназначен специально для менеджера памяти, чтобы менять каталог при выполнении вызова exec. Когда пользователь запускает в своем рабочем каталоге файл, скажем, a.out, менеджеру памяти проще перейти в этот каталог, чем раздумывать, где он находится.

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

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

Защита

Механизм ограничения доступа в MINIX основан на битах rwx. Это три набора битов, каждый из которых определяет доступность файла для его владельца, фуппы и для остальных. Значениями этих битов можно управлять при помощи системного вызова chmod, инициируемого функцией do chmod из файла protect.c. Она сначала делает ряд проверок, а затем меняет режим доступа к файлу.

Вызов chown подобен вызову chmod в том, что он тоже меняет значения внутренних полей i-узла некоторого файла. Поэтому их реализация тоже достаточно



1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 103 104 105 106 107 108 109 110 111 112 113 114 115 116 117 118 119 120 121 122 123 124 125 126 127 128 129 130 131 132 133 134 135 136 137 138 139 140 141 142 143 144 145 146 147 148 149 150 151 152 153 154 155 156 157 158 159 160 161 162 163 164 165 166 167 168 169 170 171 172 173 174 175 176 [ 177 ] 178 179 180 181 182 183 184 185 186 187

© 2000 - 2018 ULTRASONEX-AMFODENT.RU.
Копирование материалов разрешено исключительно при условии цититирования.