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

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

Здесь при первом своем вызове new block выделяет зону 12 (блоки 24 и 25). Затем она использует блок 25, который уже выделен, но еще не использован. При третьем вызове выделяется зона 20 (блоки 40 и 41) и т. д.

Функция zero block очищает блок, стирая его предыдущее содержимое. Честно говоря, это описание длиннее, чем сам код.

Каналы ввода/вывода

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

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

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

Функция pipe check делает различные проверки, выясняя, возможна ли работа с каналом. В дополнение к этим проверкам, которые могут привести к приостановке вызывающего процесса, pipe check вызывает release, чтобы определить, может ли быть оживлен ранее приостановленный процесс, пытавшийся прочитать отсутствующие данные или злоупотребляющий записью. За возобновление пишущих процессов отвечает код на строке 113, читающих - код на строке 152. Здесь же обнаруживаются некорректно проложенные или сломанные (то есть без читателей) каналы.

За приостановку процесса отвечает функция suspend. Она просто сохраняет в таблице процессов параметры вызова и устанавливает в TRUE флаг dont reply, чтобы файловая система не отправляла ответное сообщение.

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

Последняя процедура в pipe.c называется do unpause. Когда менеджер памяти пытается передать процессу сигнал, он обязан узнать, не приостановлен ли процесс на доступе к каналу или к специальному файлу (если это так, процесс будет разбужен с ошибкой EINTR). Так как менеджер памяти о каналах и специальных файлах никто в известность не ставил, он просит совета у файловой системы, передавая ей сообщение. Это сообщение обрабатывается функцией do unpause, ко-



торая возобновляет работу процесса в том слзае, если он заблокирован. Как и revive, do unpause имеет сходство с системным вызовом, хотя и не относится к ним.

5.7.5. Каталоги и пути

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

Преобразование пути в i-узел

Многие системные вызовы принимают в качестве входного аргумента пути (то есть имена файлов). Это, например, вызовы open, unlink, mount. Большинству из них, перед тем как начать выполнять сам вызов, требуется определить г-узел указанного файла. Поэтому теперь мы подробно изучим, как имя файла преобразуется в г-узел. Общие контуры уже были обрисованы на рис. 5.12.

Разбором имен файлов занимается код в path.c. Первая его процедура, eat path, получает на входе указатель на имя файла, разбирает имя, загружает нужный г-узел в память и возвращает указатель на узел. Она выполняет свою задачу при помощи функции last dir, возвращающей г-узел каталога, в котором непосредственно находится файл. Затем, чтобы получить последний компонент пути, она вызывает advance. Если поиск объекта закончился неудачей, например, такое может произойти, если один из каталогов в пути не существует или существует, но недоступен для поиска, вместо указателя на г-узел возвращается значение NIL.INODE.

Имена файлов могут быть абсолютными или относительными и могут иметь произвольное число компонентов, разделенных слэшами. Распознаванием занимается last dir. Сначала она проверяет первый символ пути с целью выяснить, абсолютный тот или относительный. Если путь абсолютный, в rip записывается указатель на корневой г-узел, для относительных путей в эту переменную помещается указатель на г-узел рабочего каталога.

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

Функция get name является вспомогательной процедурой, извлекающей компоненты пути из строк. Более интересна функция advance, которая получает на входе указатель на каталог и строку и ищет указанную строку в каталоге. Если ей удается обнаружить в каталоге объект с таким именем, она возвращает указатель на его г-узел. Эта же функция учитывает особенности смонтированных файловых систем.

Хотя advance и управляет процессом поиска строки, самим сравнением строк с записями в каталоге занимается функция search dir. Это единственный элемент во всей файловой системе, который непосредственно имеет дело с файлами каталогов. В функции есть два вложенных цикла, во внешнем перебираются блоки



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

Преобразование

пути в i-узел

Ciast dir~ конечной директории

(lvance Цикл

по компонентам пути



Обработка одного компонента


Загрузка

(read m (et block puLblock

Определение Поиск бпока Возврат блока адресов в кэше в кэш

на диске

Рис. 5.34. Некоторые из процедур, участвующих в поиске файла по его пути

Монтирование файловых систем

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

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

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

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

♦ у монтируемой файловой системы неправильная сигнатура;

♦ монтируемая файловая систем некорректна (то есть нет г-узлов);

♦ файл, к которому присоединяется файловая система, не существует или является специальным файлом;

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



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