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

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

Фронт списка

Тыл списка


-> NULL

NULL

фронт списка

NULL

Тыл списка


NULL

NULL

Тыл списка

фронт списка


NULL

Рис. 5.30. Инициализация кэша блоков: а - начальное состояние; б - после запроса одного блока; а - после того как блок освобожден

Если значение параметра ramsize меньше объема корневой файловой системы, RAM-диск увеличивается, чтобы вместить ее. Если же RAM-диск вмещает всю



корневую файловую систему и на нем еще остается место, производится подстройка с целью подогнать размер диска под объем файловой системы. Чтобы записать новую информацию в суперблок, вызывается функция put.bLock. Это единственный случай, когда суперблок модифицируется.

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

Последняя функция в main.c - load super - выполняет инициализацию таблицы суперблоков и считывает суперблок корневого устройства.

5.7.4. Работа с отдельными файлами

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

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

Файл open.с содержит код шести системных вызовов: creat, open, mknod, mkdir, close и Iseek. Вызовы creat и open мы рассмотрим вместе, а затем перейдем к остальным.

В более старых версиях UNIX вызовы creat и open служили для разных целей. При попытке открыть несуществующий файл возникала ошибка, а новый файл должен был создаваться при помощи creat, другой задачей которого является установка размера файла в нулевое значение. Но в современной POSIX-системе два отдельных вызова не требуются. По POSIX, созданием файла или обнулением старого должен заниматься вызов open, поэтому возможности creat теперь составляют лишь часть потенциала open, и нужен он только для совместимости со старыми программами. Процедуры, выполняющие действия creat и open, называются соответственно do creat и do open (как и в случае с менеджером памяти, здесь соблюдается соглашение именовать обработчик системного вызова ххх как do xxx). Открытие или создание файла включает три шага.

1. Поиск г-узла (или выделение и инициализация нового г-узла, если файл создается).

2. Поиск или создание записи в каталоге.

3. Настройка дескриптора файла и его возврат.

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

Процедура common open начинает с того, что проверяет наличие свободных файловых дескрипторов и ячеек в таблице filp. Затем, если при вызове было ука-



зано создать новый файл (то есть установлен бит 0 CREAT), вызывается функция new node. Если запись в каталоге уже присутствует, эта функция возвращает указатель на существующий г-узел, в противном случае она создает новую запись и г-узел. Если г-узел не может быть создан, функция записывает код ошибки в глобальную переменную err code. Наличие кода ошибки не обязательно означает сбой. Когда new node обнаруживает одноименный файл, она сигнализирует об этом через код ошибки, но в действительности здесь нет ничего противоправного. При неустановленном бите 0 CREAT поиск г-узла осуществляется альтернативным методом, через посредство функции eat pat из состава файла path.с, которую мы обсудим позже. На данном этапе важно лишь знать, что если г-узел не удалось ни найти, ни создать, работа common open завершается с ошибкой прежде, чем начинается выделение файлового дескриптора. Иначе функция продолжает работу, назначая файлу дескриптор и запрашивая запись в таблице filp. Следующий блок кода пропускается, если файл создается именно сейчас.

Если же файл существовал ранее, файловая система должна определить, что это за файл, какие разрешения выставлены у него и т. д., чтобы выяснить, может ли он быть открыт. Проверку битов rwx (то есть битов, управляющих доступом) выполняет вызов forbidden. Если файл представляет собой обычный файл и при вызове был установлен бит 0 TRUNC, длина файла приравнивается нулю и снова вызывается forbidden, на этот раз чтобы проверить доступность файла на запись. Когда запись разрешена, вызываются функции wipejnode и rwjnode, очищающие г-узел и сохраняющие его на диске. Для других типов файлов (каталогов, специальных файлов и каналов ввода/вывода) делаются соответствующие проверки. Так, в случае устройства, при помощи структуры dmap выполняется вызов нужной процедуры, которая открывает его. За открытие именованного канала отвечает функция pipe open, для него выполняются различные проверки, имеющие отношение к каналам.

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

Отложим в сторону файлы и займемся каталогами. И для начала поглядим на работу функции new node, что занимается выделением г-узла для вызовов creat и open. Обратившись к ней, мы вводим в рассмотрение путь к файлу. Она также используется системными вызовами mknod и mkdir, которые еще будут обсуждаться. Сначала эта функция разбирает путь к файлу, то есть просматривает его компонент за компонентом, пока не достигает конечного каталога. При помощи функции advance проверяется, может ли быть открыт последний компонент.

Например, если сделан вызов

fd = create /usr/ast/foobar . 0755):



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.
Копирование материалов разрешено исключительно при условии цититирования.