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

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

принятой в UNIX, которую вы видели на рис. 5.11. Если системе передан путь /usr/ast/mbox, она сначала ищет запись usr в корневом каталоге, затем - ast в /usr и, наконец, пытается найти mbox в /usr/ast. Как продемонстрировано на рис. 5.12, путь к файлу обрабатывается по одному компоненту за раз.

Единственная сложность возникает тогда, когда встречается смонтированная файловая система. В обычной конфигурации MINIX, как и во многих других UNIX-подобных операционных системах, имеется небольшая корневая файловая система, содержащая основные файлы, необходимые для запуска и обслуживания системы, а основное большинство файлов, включая пользовательские каталоги, находятся на отдельном устройстве, монтируемом в /usr.

Итак, настало время посмотреть, как работает монтирование. Когда пользователь вводит с терминала команду

mount /dev/hd2c /usr

файловая система, размещенная на втором разделе жесткого диска, монтируется в каталог /usr корневой файловой системы. Файловые системы до и после монтирования показаны на рис. 5.28.

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

Файловая система до монтирования

После монтирования

/libbin

./usr /bal

/balim

/ast /lib

/bin ~/usr

/ast/f1 /ast/f2

/usr/bal

/bal /USI

/usr/ast

a б e /usr/ast/f2

Рис. 5.28. a - корневая файловая система; б - не монтированная файловая система; 8 - результат монтирования файловой системы с (б) в каталог /usr



Ключевым моментом при монтировании является флаг, который устанавливается в хранящейся в памяти копии г-узла каталога /usr после успешного подсоединения. Этот флаг означает, что в данный каталог встроена файловая система. Кроме того, вызов mount загружает суперблок файловой системы в таблицу super block и устанавливает два указателя на него. Дополнительно вызов записывает корневой г-узел смонтированной файловой системы в таблицу inode.

На рис. 5.25 можно увидеть, что в копии суперблока в памяти есть два поля, относящихся к монтированию файловых систем. В первое из них, i-node-of-the-mounted-file-system, записывается ссылка на корневой i-узел смонтированной файловой системы. Второе поле, i-node-mounted-on, хранит номер г-узла точки монтирования файловой системы, например, в нашем случае это будет г-узел /usr. Два этих поля служат для соединения смонтированной и корневой файловых систем и представляют собой тот самый клей , который удерживает их вместе (на рис. 5.28, в это изображено точками). Благодаря этим полям и работают смонтированные файловые системы.

Когда файловой системе передается путь наподобие /usr/ast/f2, она увидит установленный в г-узле каталога /usr флаг и поймет, что продолжать поиск файла нужно с г-узла файловой системы, смонтированной в каталоге /usr. Возникает вопрос: Как же она найдет этот корневой г-узел?

Ответ прост. Система перебирает все хранящиеся в памяти суперблоки, пока не встретит тот, у которого поле i-node-mounted-on указывает на /usr. Это должен быть суперблок файловой системы, смонтированный в каталог /usr. Обнаружив его, несложно определить корневой г-узел соответствующей файловой системы. После этого можно продолжить поиск файла. В данном случае файловая система перейдет в каталог ast в корневом каталоге второго раздела жесткого диска.

5.6.7. Дескрипторы файлов

После того как файл открыт, пользователю возвращается дескриптор этого файла, который впоследствии может использоваться в системных вызовах read или write. В данном разделе мы рассмотрим, как файловая система обращается с дескрипторами.

Как и менеджер памяти и задача системы, файловая система поддерживает в своем адресном пространстве собственную часть таблицы процессов. Особенно интересны три поля этой таблицы. Первые два из них содержат указатели на корневой и рабочий каталоги. Поиск файла всегда начинается с одного из указанных каталогов, в зависимости от того, задан абсолютный или относительный путь. Значения этих указателей можно обновить при помощи системных вызовов chroot и chdir, которые изменяют соответственно текущие корневой и рабочий каталоги.

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



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

К несчастью, этот простой план обречен на провал, так как в MINIX (как и в UNIX) можно совместно работать с файлом. Возникающая проблема связана с 32-битным числом, индицирующим, какой байт будет считан следующим. Это тот самый номер, называемый указателем файла (или указателем позиции в файле), который меняется системным вызовом Iseek. Проблема выражается следующим вопросом: Где должен храниться указатель файла?

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

А что насчет того, чтобы поместить его в таблицу процессов? Почему бы не взять второй массив, параллельный массиву файловых дескрипторов, в котором хранить файловый указатель для каждого файла? Эта идея также не работает, хотя и по более тонкой причине. Основная подоплека проблемы кроется в семантике системного вызова fork. Когда процесс ветвится, то и родительский, и дочерний процессы должны разделять единый указатель для всех открытых файлов.

Чтобы лучше понять проблему, представим себе сценарий оболочки, в котором стандартный вывод перенаправлен в файл. Когда оболочка ответвляет от себя первую программу, позиция в файле стандартного вывода для нее равна 0. Это значение наследуется потомком, который выводит в стандартный вывод, предположим, 1 Кбайт данных. После завершения потомка значение указателя должно быть равно 1 К.

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

Таким образом, и в таблице процессов нельзя хранить файловые указатели. Они действительно должны разделяться. Для решения этой проблемы в MINIX используется новая разделяемая таблица, называемая filp. В ней хранятся значения всех файловых указателей. Применение этой таблицы демонстрируется на рис. 5.29. Благодаря тому что файловые указатели действительно используются совместно, можно корректно реализовать семантику вызова fork, и сценарии оболочки заработают правильно.

Единственным обязательным значением, которое необходимо хранить в таблице filp, является значение файлового указателя, но для удоГства туда же записывается и указатель на г-узел. Массив файловых дескрипторов в таблице процессов при этом содержит указатели на записи в массиве filp. Кроме того, в таблице



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