В предыдущей главе нами были рассмотрены сильносвязанные многопроцессор-
ные  системы  с общей памятью, общими структурами данных ядра и общим пулом,
из которого процессы вызываются на выполнение. Часто, однако,  бывает  жела-
тельно  в  целях обеспечения совместного использования ресурсов распределять
процессоры таким образом, чтобы они были автономны от операционной  среды  и
условий  эксплуатации.  Пусть, например, пользователю персональной ЭВМ нужно
обратиться к файлам, находящимся на более крупной машине, но  сохранить  при
этом контроль над персональной ЭВМ. Несмотря на то, что отдельные программы,
такие  как uucp, поддерживают передачу файлов по сети и другие сетевые функ-
ции, их использование не будет скрыто от пользователя,  поскольку  пользова-
тель  знает  о  том,  что он работает в сети. Кроме того, надо заметить, что
программы, подобные текстовым редакторам, с удаленными файлами, как с  обыч-
ными, не работают. Пользователи должны располагать стандартным набором функ-
ций  системы  UNIX  и,  за исключением возможной потери в быстродействии, не
должны ощущать пересечения машинных границ. Так, например, работа  системных
функций  open  и read с файлами на удаленных машинах не должна отличаться от
их работы с файлами, принадлежащими локальным системам.
    Архитектура распределенной системы представлена на Рисунке 13.1.  Каждый
компьютер,  показанный на рисунке, является автономным модулем, состоящим из
ЦП, памяти и периферийных устройств. Соответствие модели не нарушается  даже
несмотря на то, что компьютер не располагает локальной файловой системой: он
должен  иметь  периферийные  устройства  для связи с другими машинами, а все
принадлежащие ему файлы могут располагаться и на ином компьютере. Физическая
память, доступная каждой машине, не зависит  от  процессов,  выполняемых  на
других машинах. Этой особенностью распределенные системы отличаются от силь-
носвязанных  многопроцессорных систем, рассмотренных в предыдущей главе. Со-
ответственно, и ядро

+-----------------------------+    +-----------------------------+
|       +------------+        |    |       +------------+        |
|       | Процессоры |        |    |       | Процессоры |        |
|       +-----+------+        |    |       +-----+------+        |
| ----+-------+------+------- |    | ----+-------+------+------- |
| +---+----+ +-------+------+ |    | +---+----+ +-------+------+ |
| | Память | | Периферийные | |    | | Память | | Периферийные | |
| |        | |  устройства  | |    | |        | |  устройства  | |
| +--------+ +--------------+ +-++-+ +--------+ +--------------+ |
+-----------------------------+ ++ +-----------------------------+
                                |
                  +-------------+---------------+
                  |       +------------+        |
                  |       | Процессоры |        |
                  |       +-----+------+        |
                  | ----+-------+------+------- |
                  | +---+----+ +-------+------+ |
                  | | Память | | Периферийные | |
                  | |        | |  устройства  | |
                  | +--------+ +--------------+ |
                  +-----------------------------+

    Рисунок 13.1. Модель системы с распределенной архитектурой

                                    381


системы на каждой машине функционирует независимо от внешних условий эксплу-
атации распределенной среды.
    Распределенные системы, хорошо описанные в литературе,  традиционно  де-
лятся на следующие категории:
  *  периферийные  системы,  представляющие собой группы машин, отличающихся
    ярковыраженной общностью и связанных с одной (обычно более крупной)  ма-
    шиной. Периферийные процессоры делят свою нагрузку с центральным процес-
    сором  и переадресовывают ему все обращения к операционной системе. Цель
    периферийной системы состоит в увеличении общей производительности  сети
    и  в  предоставлении  возможности выделения процессора одному процессу в
    операционной среде UNIX. Система запускается как отдельный модуль; в от-
    личие от других моделей распределенных систем, периферийные  системы  не
    обладают  реальной  автономией, за исключением случаев, связанных с дис-
    петчеризацией процессов и распределением локальной памяти.
  * распределенные системы типа "Newcastle", позволяющие  осуществлять  дис-
    танционную связь по именам удаленных файлов в библиотеке (название взято
    из  статьи "The Newcastle Connection" - см. [Brownbridge 82]). Удаленные
    файлы имеют спецификацию (составное имя), которая в указании пути поиска
    содержит специальные символы или дополнительную компоненту имени,  пред-
    шествующую  корню файловой системы. Реализация этого метода не предпола-
    гает внесения изменений в ядро системы, вследствие этого он более прост,
    чем другие методы, рассматриваемые в этой главе, но менее гибок.
  * абсолютно "прозрачные" распределенные системы, в которых для обращения к
    файлам, расположенным на других машинах, достаточно указания их стандар-
    тных составных имен; распознавание этих файлов как  удаленных  входит  в
    обязанности  ядра. Маршруты поиска файлов, указанные в их составных име-
    нах, пересекают машинные границы в точках монтирования, сколько бы таких
    точек ни было сформировано при монтировании файловых систем на дисках.

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




    Архитектура периферийной системы показана на Рисунке  13.2.  Цель  такой
конфигурации состоит в повышении общей производительности сети за счет пере-
распределения  выполняемых  процессов между центральным и периферийными про-
цессорами. У каждого из периферийных процессоров нет в  распоряжении  других
локальных  периферийных  устройств, кроме тех, которые ему нужны для связи с
центральным процессором. Файловая система и все устройства находятся в  рас-
поряжении  центрального  процессора.  Предположим,  что все пользовательские
процессы исполняются на периферийном процессоре и между  периферийными  про-
цессорами не перемещаются; будучи однажды переданы процессору, они пребывают
на  нем  до  момента завершения. Периферийный процессор содержит облегченный
вариант операционной системы, предназначенный для обработки локальных  обра-
щений к системе, управления прерываниями, распределения памяти, работы с се-
тевыми протоколами и с драйвером устройства связи с центральным процессором.

                                    382

    При инициализации системы на центральном процессоре ядро по линиям связи
загружает  на каждом из периферийных процессоров локальную операционную сис-
тему. Любой выполняемый на периферии процесс связан  с  процессом-спутником,
принадлежащим  центральному  процессору  (см.  [Birrell 84]); когда процесс,
протекающий на периферийном процессоре, вызывает системную функцию,  которая
нуждается в услугах исключительно центрального процессора, периферийный про-
цесс связывается со своим спутником и запрос поступает на обработку на цент-
ральный  процессор.  Процесс-спутник  исполняет системную функцию и посылает
результаты обратно на периферийный процессор. Взаимоотношения  периферийного
процесса  со своим спутником похожи на отношения клиента и сервера, подробно
рассмотренные нами в главе 11: периферийный процесс выступает клиентом свое-
го спутника, поддерживающего функции работы с файловой  системой.  При  этом
удаленный процесс-сервер имеет только одного клиента. В разделе 13.4 мы рас-
смотрим процессы-серверы, имеющие несколько клиентов.

    Центральный процессор              Периферийный процессор
+-----------------------------+    +-----------------------------+
|       +------------+        |    |       +------------+        |
|       | Процессоры |        |    |       | Процессоры |        |
|       +-----+------+        |    |       +-----+------+        |
| ----+-------+------+------- |    | ----+-------+-------------- |
| +---+----+ +-------+------+ |    | +---+----+                  |
| | Память | | Периферийные | |    | | Память |                  |
| |        | |  устройства  | |    | |        |                  |
| +--------+ +--------------+ +-++-+ +--------+                  |
+-----------------------------+ ++ +-----------------------------+
                                |
                  +-------------+---------------+
                  |       +------------+        |
     Периферийный |       | Процессоры |        |
     процессор    |       +-----+------+        |
                  | ----+-------+-------------- |
                  | +---+----+                  |
                  | | Память |                  |
                  | |        |                  |
                  | +--------+                  |
                  +-----------------------------+

           Рисунок 13.2. Конфигурация периферийной системы


    Когда периферийный процесс вызывает системную функцию, которую можно об-
работать  локально,  ядру  нет надобности посылать запрос процессу-спутнику.
Так, например, в целях получения дополнительной памяти процесс может вызвать
для локального исполнения функцию sbrk. Однако, если требуются услуги  цент-
рального  процессора, например, чтобы открыть файл, ядро кодирует информацию
о передаваемых вызванной функции параметрах и условиях выполнения процесса в
некое сообщение,  посылаемое  процессу-спутнику  (Рисунок  13.3).  Сообщение
включает в себя признак, из которого следует, что системная функция выполня-
ется  процессом-спутником от имени клиента, передаваемые функции параметры и
данные о среде выполнения процесса (например, пользовательский  и  групповой
коды  идентификации),  которые для разных функций различны. Оставшаяся часть
сообщения представляет собой данные переменной  длины  (например,  составное
имя файла или данные, предназначенные для записи функцией write).
    Процесс-спутник ждет поступления запросов от периферийного процесса; при
получении запроса он декодирует сообщение, определяет тип системной функции,
исполняет ее и преобразует результаты в ответ, посылаемый периферийному про-
цессу.  Ответ,  помимо  результатов выполнения системной функции, включает в
себя сообщение об

                                    383

Формат сообщения
+----------------+----------+---------------+--------------------+
| Признак вызова |Параметры |Данные о среде |    Составное имя   |
| системной функ-|системной |выполнения про-|-------  или  ------|
| ции            |функции   |цесса          |    поток данных    |
+----------------+----------+---------------+--------------------+

    Ответ
    +------------+-----------+---------+---------------------+
    | Результаты | Сообщение | Номер   |                     |
    | выполнения | об ошибке | сигнала |---- Поток данных ---|
    | системной  |           |         |                     |
    | функции    |           |         |                     |
    +------------+-----------+---------+---------------------+

                 Рисунок 13.3. Форматы сообщений


ошибке (если она имела место), номер сигнала и массив данных переменной дли-
ны, содержащий, например, информацию,  прочитанную  из  файла.  Периферийный
процесс приостанавливается до получения ответа, получив его, производит рас-
шифровку  и  передает  результаты пользователю. Такова общая схема обработки
обращений к операционной системе; теперь перейдем к более  детальному  расс-
мотрению отдельных функций.
    Для  того, чтобы объяснить, каким образом работает периферийная система,
рассмотрим ряд функций: getppid, open, write, fork, exit и  signal.  Функция
getppid  довольно проста, поскольку она связана с простыми формами запроса и
ответа, которыми обмениваются периферийный и центральный процессоры. Ядро на
периферийном процессоре формирует сообщение, имеющее  признак,  из  которого
следует,  что  запрашиваемой  функцией  является функция getppid, и посылает
запрос центральному процессору. Процесс-спутник  на  центральном  процессоре
читает  сообщение  с  периферийного процессора, расшифровывает тип системной
функции, исполняет ее и получает идентификатор  своего  родителя.  Затем  он
формирует ответ и передает его периферийному процессу, находящемуся в состо-
янии  ожидания на другом конце линии связи. Когда периферийный процессор по-
лучает  ответ,  он  передает  его  процессу,  вызвавшему  системную  функцию
getppid.  Если же периферийный процесс хранит данные (такие, как идентифика-
тор процесса-родителя) в локальной памяти, ему вообще не придется связывать-
ся со своим спутником.
    Если производится обращение к системной функции open, периферийный  про-
цесс  посылает  своему  спутнику соответствующее сообщение, которое включает
имя файла и другие параметры. В случае успеха процесс-спутник  выделяет  ин-
декс  и точку входа в таблицу файлов, отводит запись в таблице пользователь-
ских дескрипторов файла в своем пространстве и возвращает  дескриптор  файла
периферийному процессу. Все это время на другом конце линии связи периферий-
ный процесс ждет ответа. У него в распоряжении нет никаких структур, которые
хранили бы информацию об открываемом файле; возвращаемый функцией open деск-
риптор  представляет  собой  указатель  на запись в таблице пользовательских
дескрипторов файла, принадлежащей процессу-спутнику.  Результаты  выполнения
функции показаны на Рисунке 13.4.
    Если производится обращение к системной функции write, периферийный про-
цессор формирует сообщение, состоящее из признака функции write, дескриптора
файла и объема записываемых данных. Затем из пространства периферийного про-
цесса  он  по линии связи копирует данные процессу-спутнику. Процесс-спутник
расшифровывает полученное сообщение, читает данные из линии связи и  записы-
вает  их  в  соответствующий файл (в качестве указателя на индекс которого и
запись о котором в таблице файлов используется содержащийся в сообщении дес-
криптор); все указанные действия выполняются на центральном  процессоре.  По


                                    384

         Центральный процессор             Периферийный процессор
+--------------------------------------+   +---------------------+
|                    таблица           |   |                     |
|                    пользо-           |   |                     |
|                    ватель-           |   |                     |
|                    ских              |   |                     |
|                    дескрип-          |   |                     |
| таблица   таблица  торов             |   |                     |
| индексов  файлов   файла   +--------+|   |     +---------+     |
| +-----+   +-----+  +-----+ |Процесс-|----------| Процесс |     |
| |     |   |     |  |     | |спутник ||   |     +---------+     |
| +-----+   +-----+  +-----+ +-+------+|   |                     |
| |    -+-+ |     | ++-   -+---+       |   |                     |
| +-----+ | +-----+ |+-----+ дескрип-  |   |                     |
| |     | +-+-   -+-+|     | тор файла |   |                     |
| +-----+   +-----+  +-----+           |   |                     |
| |     |   |     |                    |   |                     |
| +-----+   +-----+                    |   |                     |
| |     |   |     |                    |   |                     |
| +-----+   +-----+                    |   |                     |
+--------------------------------------+   +---------------------+

    Рисунок 13.4. Вызов функции open из периферийного процесса


окончании  работы  процесс-спутник  передает периферийному процессу посылку,
подтверждающую прием сообщения и содержащую количество байт данных,  успешно
переписанных  в файл. Операция read выполняется аналогично; спутник информи-
рует периферийный процесс о количестве реально прочитанных  байт  (в  случае
чтения данных с терминала или из канала это количество не всегда совпадает с
количеством, указанным в запросе). Для выполнения как той, так и другой фун-
кции  может потребоваться многократная пересылка информационных сообщений по
сети, что определяется объемом пересылаемых данных и размерами сетевых паке-
тов.
    Единственной функцией, требующей внесения изменений при работе на  цент-
ральном процессоре, является системная функция fork. Когда процесс исполняет
эту  функцию на ЦП, ядро выбирает для него периферийный процессор и посылает
сообщение специальному процессу -серверу, информируя последний  о  том,  что
собирается  приступить к выгрузке текущего процесса. Предполагая, что сервер
принял запрос, ядро с помощью функции fork создает новый  периферийный  про-
цесс,  выделяя запись в таблице процессов и адресное пространство. Централь-
ный процессор выгружает копию процесса, вызвавшего функцию fork, на  перифе-
рийный  процессор,  затирая только что выделенное адресное пространство, по-
рождает локальный спутник для связи с новым периферийным процессом и посыла-
ет на периферию сообщение о необходимости инициализации счетчика команд  для
нового процесса. Процесс-спутник (на ЦП) является потомком процесса, вызвав-
шего функцию fork; периферийный процесс с технической точки зрения выступает
потомком  процесса-сервера, но по логике он является потомком процесса, выз-
вавшего функцию fork. Процесс-сервер не имеет логической связи с потомком по
завершении функции fork; единственная задача сервера состоит в оказании  по-
мощи  при  выгрузке  потомка. Из-за сильной связи между компонентами системы
(периферийные процессоры не располагают автономией) периферийный  процесс  и
процесс-спутник  имеют  один  и  тот же код идентификации. Взаимосвязь между
процессами показана на Рисунке 13.5: непрерывной линией показана связь  типа
"родитель-потомок", пунктиром - связь между равноправными партнерами.
    Когда  процесс исполняет функцию fork на периферийном процессоре, он по-
сылает сообщение своему спутнику на ЦП, который и исполняет после этого  всю
вышеописанную последовательность действий. Спутник выбирает новый периферий-


                                    385

     Центральный процессор            Периферийный процессор
    +----------------------+         +----------------------+
    | +------------------+ |         | +------------------+ |
    | | Процесс-родитель |-------------|  Процесс-сервер  | |
    | +---------+--------+ |         | +------------------+ |
    |           |          |         |                      |
    |           |          |         |                      |
    | +---------+--------+ |         | +------------------+ |
    | | Порожденный спут-|-------------| Порожденный про- | |
    | |        ник       | |         | |       цесс       | |
    | +------------------+ |         | +------------------+ |
    +----------------------+         +----------------------+

    Рисунок 13.5. Выполнение функции fork на центральном процессоре


ный  процессор  и делает необходимые приготовления к выгрузке образа старого
процесса: посылает периферийному процессу-родителю запрос на чтение его  об-
раза,  в  ответ  на который на другом конце канала связи начинается передача
запрашиваемых данных. Спутник считывает передаваемый  образ  и  переписывает
его   периферийному  потомку.  Когда  выгрузка  образа  заканчивается,  про-
цесс-спутник исполняет функцию fork, создавая своего потомка на ЦП, и  пере-
дает значение счетчика команд периферийному потомку, чтобы последний знал, с
какого  адреса начинать выполнение. Очевидно, было бы лучше, если бы потомок
процесса-спутника назначался периферийному потомку в качестве родителя,  од-
нако  в нашем случае порожденные процессы получают возможность выполняться и
на других периферийных процессорах, а не только на том, на котором они  соз-
даны.  Взаимосвязь  между  процессами по завершении функции fork показана на
Рисунке 13.6. Когда периферийный процесс завершает свою работу, он  посылает
соответствующее  сообщение процессу-спутнику и тот тоже завершается. От про-
цесса-спутника инициатива завершения работы исходить не может.

                       Центральный процессор
    +-------------------------------------------------------+
    |   +------------------+          +-----------------+   |
    |   | Спутник-родитель +----------+ Спутник-потомок |   |
    |   +------------------+          +-----------------+   |
    |             -                            -            |
    +-------------------------------------------------------+
                -                                -
+---------------------------+        +---------------------------+
|             -             |        |             -             |
| +-----------------------+ |        | +----------------------+  |
| | Периферийный родитель | |        | | Периферийный потомок |  |
| +-----------------------+ |        | +----------------------+  |
+---------------------------+        +---------------------------+
    Периферийный процессор               Периферийный процессор

    Рисунок 13.6. Выполнение функции fork на периферийном процессоре


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

                                    386

полнение функции аварийно,  процессу-спутнику  в  многопроцессорной  системе
следует вести себя тем же образом. То же самое можно сказать и о том случае,
когда  сигнал  побуждает процесс к завершению своей работы с помощью функции
exit: периферийный процесс завершается и посылает соответствующее  сообщение
процессу-спутнику, который, разумеется, тоже завершается.
    Когда  периферийный процесс вызывает системную функцию signal, он сохра-
няет текущую информацию в локальных таблицах  и  посылает  сообщение  своему
спутнику, информируя его о том, следует ли указанный сигнал принимать или же
игнорировать.  Процессу-спутнику  безразлично, выполнять ли перехват сигнала
или действие по умолчанию. Реакция процесса на сигнал зависит от трех факто-
ров (Рисунок 13.7): поступает ли сигнал во время выполнения  процессом  сис-
темной  функции, сделано ли с помощью функции signal указание об игнорирова-
нии сигнала, возникает ли сигнал на этом же периферийном процессоре  или  на

    +------------------------------------------------------------+
    | алгоритм sighandle    /* алгоритм обработки сигналов */    |
    | входная информация:  отсутствует                           |
    | выходная информация: отсутствует                           |
    | {                                                          |
    |    если (текущий процесс является чьим-то спутником или    |
    |     имеет прототипа)                                       |
    |    {                                                       |
    |       если (сигнал игнорируется)                           |
    |           вернуть управление;                              |
    |       если (сигнал поступил во время выполнения системной  |
    |        функции)                                            |
    |           поставить сигнал перед процессом-спутником;      |
    |       в противном случае                                   |
    |           послать сообщение о сигнале периферийному процес-|
    |            су;                                             |
    |    }                                                       |
    |    в противном случае       /* периферийный процесс */     |
    |    {                                                       |
    |       /* поступил ли сигнал во время выполнения системной  |
    |        * функции или нет                                   |
    |        */                                                  |
    |       послать сигнал процессу-спутнику;                    |
    |    }                                                       |
    | }                                                          |
    |                                                            |
    | алгоритм satellite_end_of_syscall    /* завершение систем- |
    |                                       * ной функции, выз-  |
    |                                       * ванной периферийным|
    |                                       * процессом */       |
    | входная информация:  отсутствует                           |
    | выходная информация: отсутствует                           |
    | {                                                          |
    |    если (во время выполнения системной функции поступило   |
    |     прерывание)                                            |
    |       послать периферийному процессу сообщение о прерыва-  |
    |        нии, сигнал;                                        |
    |    в противном случае    /* выполнение системной функции не|
    |                           * прерывалось */                 |
    |       послать ответ: включить флаг, показывающий поступле- |
    |        ние сигнала;                                        |
    | }                                                          |
    +------------------------------------------------------------+

       Рисунок 13.7. Обработка сигналов в периферийной системе

                                    387



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

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


             Периферийный процесс             Процесс-спутник
    +------------------------------------------------------------
    |    Вызывает системную функцию read              -
    |   Посылает сообщение о вызове функции           -
    |          процессу-спутнику                      -
    |    Приостанавливается до получения              -
    |      ответа от процесса-спутника       Получает сообщение о
    |                   -                   вызове системной функ-
    |                   -                         ции read
    |                   -                    Читает данные с тер-
    |                   -                          минала
    |                   -                    Приостанавливается в
    |                   -                     ожидании получения
    |                   -                       порции данных
    |                   -                             -
    |                   -                             -
    |                   -                    Сигнал (пользователь
    |                   -                   нажал клавишу "break")
    |                   -                    Выходит из состояния
    |                   -                         приостанова
    |                   -                    Прекращает выполнение
    |                   -                      системной функции
    |                   -                     Посылает ответ пери-
    |                   -                     ферийному процессу:
    |                   -                      выполнение функции
    |                   -                          прервано
    |     Выходит из состояния приостанова
    |            Анализирует ответ
    v           Обрабатывает сигнал

    Рисунок 13.8. Прерывание во время выполнения системной функции

                                    388


    Предположим, например, что периферийный процесс вызывает функцию  чтения
с  терминала,  связанного с центральным процессором, и приостанавливает свою
работу на время выполнения функции процессом-спутником (Рисунок 13.8).  Если
пользователь  нажимает  клавишу прерывания (break), ядро ЦП посылает процес-
су-спутнику соответствующий сигнал. Если спутник находился в состоянии  при-
останова  в  ожидании ввода с терминала порции данных, он немедленно выходит
из этого состояния и прекращает выполнение функции read. В своем  ответе  на
запрос  периферийного  процесса спутник сообщает код ошибки и номер сигнала,
соответствующий прерыванию. Периферийный процесс анализирует ответ  и,  пос-
кольку  в  сообщении  говорится о поступлении сигнала прерывания, отправляет
сигнал самому себе. Перед выходом из функции read периферийное ядро осущест-
вляет проверку поступления сигналов, обнаруживает сигнал прерывания,  посту-
пивший от процесса-спутника, и обрабатывает его обычным порядком. Если в ре-
зультате  получения  сигнала  прерывания периферийный процесс завершает свою
работу с помощью функции exit, данная функция берет на себя заботу об  унич-
тожении процесса-спутника. Если периферийный процесс перехватывает сигналы о
прерывании, он вызывает пользовательскую функцию обработки сигналов и по вы-
ходе  из  функции read возвращает пользователю код ошибки. С другой стороны,
если спутник исполняет от имени  периферийного  процесса  системную  функцию
stat,  он  не  будет  прерывать ее выполнение при получении сигнала (функции
stat гарантирован выход из любого приостанова, поскольку для нее время  ожи-
дания  ресурса  ограничено).  Спутник  доводит выполнение функции до конца и
возвращает периферийному процессу номер сигнала. Периферийный процесс  посы-
лает сигнал самому себе и получает его на выходе из системной функции.
    Если  сигнал  возник на периферийном процессоре во время выполнения сис-
темной функции, периферийный процесс будет находиться  в  неведении  относи-
тельно  того,  вернется ли к нему вскоре управление от процесса-спутника или
же последний перейдет в состояние приостанова на неопределенное время. Пери-
ферийный процесс посылает спутнику специальное сообщение, информируя  его  о
возникновении сигнала. Ядро на ЦП расшифровывает сообщение и посылает сигнал
спутнику,  реакция которого на получение сигнала описана в предыдущих параг-
рафах (аварийное завершение выполнения функции или доведение его до  конца).
Периферийный  процесс  не  может послать сообщение спутнику непосредственно,
поскольку спутник занят исполнением системной функции и не считывает  данные
из линии связи.
    Если обратиться к примеру с функцией read, следует отметить, что перифе-
рийный  процесс не имеет представления о том, ждет ли его спутник ввода дан-
ных с терминала или же выполняет другие действия. Периферийный процесс посы-
лает спутнику сообщение о сигнале: если спутник находится в состоянии приос-
танова с приоритетом, допускающим прерывания, он немедленно выходит из этого
состояния и прекращает выполнение системной функции; в противном случае  вы-
полнение функции доводится до успешного завершения.
    Рассмотрим, наконец, случай поступления сигнала во время, не связанное с
выполнением  системной  функции.  Если  сигнал  возник на другом процессоре,
спутник получает его первым и посылает  сообщение  о  сигнале  периферийному
процессу, независимо от того, касается ли этот сигнал периферийного процесса
или  нет.  Периферийное ядро расшифровывает сообщение и посылает сигнал про-
цессу, который реагирует на него обычным порядком. Если сигнал возник на пе-
риферийном процессоре, процесс выполняет стандартные действия, не прибегая к
услугам своего спутника.
    Когда периферийный процесс посылает сигнал другим  периферийным  процес-
сам,  он  кодирует  сообщение  о  вызове функции kill и посылает его процес-
су-спутнику, который исполняет вызываемую функцию локально. Если часть  про-
цессов, для которых предназначен сигнал, имеет местонахождение на других пе-
риферийных  процессорах, сигнал получат (и прореагируют на его получение вы-
шеописанным образом) их спутники.



                                    389



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

    "sftig!/fs1/mjb/rje"

идентифицирует  файл  "/fs1/mjb/rje",  находящийся  на машине "sftig". Такая
схема идентифицирования файла соответствует соглашению, установленному прог-
раммой uucp относительно передачи файлов между системами типа UNIX. В другой
схеме удаленные файлы идентифицируются добавлением к имени специального пре-
фикса, например:

    /../sftig/fs1/mjb/rje

где "/../" - префикс, свидетельствующий о том, что  файл  удаленный;  вторая
компонента  имени файла является именем удаленной машины. В данной схеме ис-


        Процесс-клиент                      Процесс-сервер
+-----------------------------+     +----------------------------+
|                   Таблица   |     |  Процесс-                  |
|  Си-библиотека    открытых  |     |  спутник         Запрос    |
|                   файлов    |     |  (пользо-        на чтение |
|                   +------+  |     |  вательский      |   |     |
|    +--------------+---   |  |     |  уровень)        |   |     |
|    |              +------+  |     |                  |   |     |
|    |  локальный   |      |  |     |    +-------------+   |     |
|    |              +------+  |     |    |                 |     |
|    |         +----+---   |  |     |    |                 |     |
|    |         |    +------+  |     |    |                 |     |
|    |         |    |      |  |     |    |                 |     |
|    |         |    +------+  |     |    |                 |     |
|    |         +-----+        |     |    |                 |     |
+----+---------------+--------+     +----+-----------------+-----+
     |               | удаленный         |                 |
+----+---------------+--------+     +----+-----------------+-----+
|    |              Сетевой   |     |    |             Сетевой   |
|  Ядро             интерфейс |     |  Ядро            интерфейс |
|                    |        |     |                      |     |
+--------------------+--------+     +----------------------+-----+
                     |              с е т ь                |
                     +-------------------------------------+

    Рисунок 13.9. Формулирование запросов к файловому серверу (процессору)

                                    390



пользуется привычный синтаксис имен файлов в системе UNIX, поэтому в отличие
от первой схемы здесь пользовательским программам нет  необходимости  прино-
равливаться  к  использованию имен, имеющих необычную конструкцию (см. [Pike
85]).
    Всю оставшуюся часть раздела мы посвятим  рассмотрению  модели  системы,
использующей  связь типа Newcastle, в которой ядро не занимается распознава-
нием удаленных файлов; эта функция полностью возлагается на подпрограммы  из
стандартной  Си-библиотеки,  выполняющие в данном случае роль системного ин-
терфейса. Эти подпрограммы анализируют первую компоненту имени файла, в обо-
их описанных способах идентифицирования содержащую признак удаленности  фай-
ла.  В  этом состоит отступление от заведенного порядка, при котором библио-
течные подпрограммы не занимаются синтаксическим разбором  имен  файлов.  На
Рисунке  13.9 показано, каким образом формулируются запросы к файловому сер-
веру. Если файл локальный, ядро локальной системы обрабатывает запрос  обыч-
ным способом. Рассмотрим обратный случай:

    open("/../sftig/fs1/mjb/rje/file",O_RDONLY);

Подпрограмма open из Си-библиотеки анализирует первые две компоненты состав-
ного  имени  файла  и  узнает,  что  файл следует искать на удаленной машине
"sftig". Чтобы иметь информацию о том, была ли ранее у процесса связь с дан-
ной машиной, подпрограмма заводит специальную структуру, в которой запомина-
ет этот факт, и в случае отрицательного ответа устанавливает связь с  файло-
вым сервером, работающим на удаленной машине. Когда процесс формулирует свой
первый запрос на дистанционную обработку, удаленный сервер подтверждает зап-
рос,  в случае необходимости ведет запись в поля пользовательского и группо-
вого кодов идентификации и создает процессспутник, который  будет  выступать
от имени процесса-клиента.
    Чтобы выполнять запросы клиента, спутник должен иметь на удаленной маши-
не те же права доступа к файлам, что и клиент. Другими словами, пользователь
"mjb" должен иметь и к удаленным, и к локальным файлам одинаковые права дос-
тупа. К сожалению, не исключена возможность того, что код идентификации кли-
ента  "mjb"  может  совпасть с кодом идентификации другого клиента удаленной
машины. Таким образом, администраторам систем на работающих в  сети  машинах
следует либо следить за назначением каждому пользователю кода идентификации,
уникального  для  всей сети, либо в момент формулирования запроса на сетевое
обслуживание выполнять преобразование кодов. Если это не будет сделано, про-
цесс-спутник будет иметь на удаленной машине права другого клиента.
    Более деликатным вопросом является получение в отношении работы  с  уда-
ленными файлами прав суперпользователя. С одной стороны, клиент-суперпользо-
ватель  не  должен иметь те же права в отношении удаленной системы, чтобы не
вводить в заблуждение средства защиты удаленной системы. С  другой  стороны,
некоторые  из  программ,  если  им  не предоставить права суперпользователя,
просто не смогут работать. Примером такой программы является программа mkdir
(см. главу 7), создающая новый каталог. Удаленная система  не  разрешила  бы
клиенту  создавать новый каталог, поскольку на удалении права суперпользова-
теля не действуют. Проблема создания удаленных  каталогов  служит  серьезным
основанием  для  пересмотра  системной функции mkdir в сторону расширения ее
возможностей в автоматическом  установлении  всех  необходимых  пользователю
связей.  Тем  не  менее, получение setuid-программами (к которым относится и
программа mkdir) прав суперпользователя по отношению к удаленным файлам  все
еще  остается  общей проблемой, требующей своего решения. Возможно, что наи-
лучшим решением этой проблемы было бы установление для файлов дополнительных
характеристик, описывающих доступ к ним со стороны удаленных  суперпользова-
телей; к сожалению, это потребовало бы внесения изменений в структуру диско-
вого  индекса (в части добавления новых полей) и породило бы слишком большой
беспорядок в существующих системах.

                                    391

    Если подпрограмма open завершается успешно, локальная библиотека  остав-
ляет об этом соответствующую отметку в доступной для пользователя структуре,
содержащей  адрес сетевого узла, идентификатор процесса-спутника, дескриптор
файла и другую аналогичную  информацию.  Библиотечные  подпрограммы  read  и
write  устанавливают, исходя из дескриптора, является ли файл удаленным, и в
случае положительного ответа  посылают  спутнику  сообщение.  Процесс-клиент
взаимодействует  со  своим  спутником  во всех случаях обращения к системным
функциям, нуждающимся в услугах удаленной машины. Если процесс обращается  к
двум файлам, расположенным на одной и той же удаленной машине, он пользуется
одним  спутником,  но если файлы расположены на разных машинах, используются
уже два спутника: по одному на каждой машине. Два спутника используются и  в
том случае, когда к файлу на удаленной машине обращаются два процесса. Вызы-
вая  системную функцию через спутника, процесс формирует сообщение, включаю-
щее в себя номер функции, имя пути поиска и другую  необходимую  информацию,
аналогичную той, которая входит в структуру сообщения в системе с периферий-
ными процессорами.
    Механизм  выполнения  операций над текущим каталогом более сложен. Когда
процесс выбирает в качестве текущего удаленный каталог,  библиотечная  подп-
рограмма посылает соответствующее сообщение спутнику, который изменяет теку-
щий  каталог,  при  этом  подпрограмма запоминает, что каталог удаленный. Во
всех случаях, когда имя пути поиска начинается с символа, отличного от  нак-
лонной  черты  (/),  подпрограмма  посылает это имя на удаленную машину, где
процесс-спутник прокладывает маршрут, начиная с текущего каталога. Если  те-
кущий каталог - локальный, подпрограмма просто передает имя пути поиска ядру
локальной  системы. Системная функция chroot в отношении удаленного каталога
выполняется похоже, но при этом ее выполнение  для  ядра  локальной  системы
проходит  незамеченным;  строго  говоря, процесс может оставить эту операцию
без внимания, поскольку только библиотека фиксирует ее выполнение.
    Когда процесс вызывает функцию fork, соответствующая библиотечная  подп-
рограмма  посылает  сообщения каждому спутнику. Процессы -спутники выполняют
операцию ветвления и посылают идентификаторы своих потомков  клиенту-родите-
лю. Процесс-клиент запускает системную функцию fork, которая передает управ-
ление  порождаемому  потомку; локальный потомок ведет диалог с удаленным по-
томком-спутником, адреса которого сохранила библиотечная подпрограмма. Такая
трактовка функции fork облегчает процессам-спутникам контроль над  открытыми
файлами и текущими каталогами. Когда процесс, работающий с удаленными файла-
ми, завершается (вызывая функцию exit), подпрограмма посылает сообщения всем
его  удаленным  спутникам,  чтобы они по получении сообщения проделали то же
самое. Отдельные моменты реализации системных функций exec и exit затрагива-
ются в упражнениях.
    Преимущество связи типа Newcastle состоит в том, что обращение  процесса
к  удаленным  файлам  становится "прозрачным" (незаметным для пользователя),
при этом в ядро системы никаких изменений вносить не нужно.  Однако,  данной
разработке присущ и ряд недостатков. Прежде всего, при ее реализации возмож-
но снижение производительности системы. В связи с использованием расширенной
Си-библиотеки размер используемой каждым процессом памяти увеличивается, да-
же если процесс не обращается к удаленным файлам; библиотека дублирует функ-
ции  ядра  и требует для себя больше места в памяти. Увеличение размера про-
цессов приводит к удлинению продолжительности периода запуска и  может  выз-
вать  большую конкуренцию за ресурсы памяти, создавая условия для более час-
той выгрузки и подкачки задач. Локальные запросы будут исполняться медленнее
из-за увеличения продолжительности каждого обращения к ядру, замедление  мо-
жет  грозить и обработке удаленных запросов, затраты по пересылке которых по
сети увеличиваются. Дополнительная обработка удаленных запросов на пользова-
тельском уровне увеличивает количество переключений контекста,  операций  по
выгрузке и подкачке процессов. Наконец, для того, чтобы обращаться к удален-
ным  файлам,  программы должны быть перекомпилированы с использованием новых
библиотек; старые программы и поставленные объектные модули без этого  рабо-
тать с удаленными файлами не смогут. Все эти недостатки отсутствуют в систе-

                                    392

ме, описываемой в следующем разделе.





    Термин "прозрачное распределение" означает, что пользователи, работающие
на одной машине, могут обращаться к файлам, находящимся на другой машине, не
осознавая того, что тем самым они пересекают машинные границы, подобно тому,
как  на своей машине они при переходе от одной файловой системе к другой пе-
ресекают точки монтирования. Имена, по которым процессы обращаются к файлам,
находящимся на удаленных машинах, похожи на имена локальных файлов:  отличи-
тельные  символы  в  них  отсутствуют. В конфигурации, показанной на Рисунке
13.10, каталог "/usr/src", принадлежащий машине B, "вмонтирован"  в  каталог
"/usr/src",  принадлежащий машине A. Такая конфигурация представляется удоб-
ной в том случае, если в разных системах предполагается использовать один  и
тот  же исходный код системы, традиционно находящийся в каталоге "/usr/src".
Пользователи, работающие на машине A, могут обращаться к файлам, расположен-
ным на машине B, используя привычный синтаксис написания имен файлов (напри-
мер: "/usr/src/cmd/login.c"), и ядро уже само решает вопрос,  является  файл
удаленным или же локальным. Пользователи, работающие на машине B, имеют дос-
туп  к своим локальным файлам (не подозревая о том, что к этим же файлам мо-
гут обращаться и пользователи машины A), но, в свою очередь, не имеют досту-
па к файлам, находящимся на машине A. Конечно, возможны и другие варианты, в
частности, такие, в которых все удаленные системы монтируются  в  корне  ло-
кальной  системы, благодаря чему пользователи получают доступ ко всем файлам
во всех системах.


            Машина A                          Машина B
+-----------------------------+    +-----------------------------+
|               /             |    |              /              |
|               |             |    |              |              |
|      +--------+--------+    |    |  +-----------+-----------+  |
|      |                 |    |    |  |           |           |  |
|     bin               usr   |    | usr         bin         etc |
|      |                 |    |    |  |                          |
| +----+----+       +----+--+ |    |  +-------+                  |
| |         |       |       | |    |  |       |                  |
|login    mail     bin     src| +--->src     bin                 |
|                   |       | | |  |  |                          |
|               +---+---+   | | |  |  +------+-----+             |
|               |       |   | | |  |  |      |     |             |
|              troff   vi   | | |  | lib    cmd   uts            |
|                           | | |  |         |                   |
|                           | | |  |     +---+---+               |
|                           | | |  |     |       |               |
|                           | | |  |  login.c   mail.c           |
+---------------------------|-+ |  +-----------------------------+
                            +---+

    Рисунок 13.10. Файловые системы после удаленного монтирования


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

                                    393

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

    cd ../../..

текущим  каталогом станет корневой каталог, принадлежащий машине A, а не ма-
шине B. Алгоритм namei, работающий в ядре удаленной системы, получив  после-
довательность символов "..", проверяет, является ли вызывающий процесс аген-
том  процесса-клиента, и в случае положительного ответа устанавливает, трак-
тует ли клиент текущий рабочий каталог в качестве корня  удаленной  файловой
системы.
    Связь  с  удаленной машиной принимает одну из двух форм: вызов удаленной
процедуры или вызов удаленной системной функции. В первой форме каждая  про-
цедура  ядра,  имеющая  дело  с индексами, проверяет, указывает ли индекс на
удаленный файл, и если это так, посылает на удаленную машину запрос  на  вы-
полнение указанной операции. Данная схема естественным образом вписывается в
абстрактную структуру поддержки файловых систем различных типов, описанную в
заключительной  части  главы  5. Таким образом, обращение к удаленному файлу
может инициировать пересылку по сети нескольких сообщений, количество  кото-
рых определяется количеством подразумеваемых операций над файлом, с соответ-
ствующим увеличением времени ответа на запрос с учетом принятого в сети вре-
мени  ожидания.  Каждый набор удаленных операций включает в себя, по крайней
мере, действия по блокированию индекса, подсчету ссылок и т.п. В целях  усо-
вершенствования  модели предлагались различные оптимизационные решения, свя-
занные с объединением нескольких операций в один запрос (сообщение) и с  бу-
феризацией наиболее важных данных (см. [Sandberg 85]).


       Сервер                   Клиент (процесс/процессор)
+--------------------+  +----------------------------------------+
| таблица            |  | таблица   таблица  таблица             |
| индексов +-------+ |  | индексов  файлов   пользо-             |
| +-----+  |Спутник|-|  | +-----+   +-----+  ватель-             |
| |     |  +-+-----+ |- | |     |   |     |  ских                |
| +-----+    |       |  - +-----+   +-----+  дескрип-   +-------+|
| |     |    |     +------+-   -+-+ |     |  торов   +--+Процесс||
| +-----+    |     | |  | +-----+ | +-----+  файла   |  +-------+|
| |     |    |     | |  | |     | +-+-   -++ +-----+ |           |
| +-----+    |     | |  | +-----+   +-----+| |     | |           |
| |     |    |     | |  | |     |   |     || +-----+ |дескриптор |
| +-----+    |     | |  | +-----+   +-----++-+-   -+-+файла      |
| |   --+----+-----+ |  | |     |   |     |  +-----+             |
| +-----+            |  | +-----+   +-----+  |     |             |
|                    |  |                    +-----+             |
+--------------------+  +----------------------------------------+

             Рисунок 13.11. Открытие удаленного файла

    Рассмотрим     процесс,     который     открывает     удаленный     файл
"/usr/src/cmd/login.c", где "src" - точка монтирования.  Выполняя  синтакси-
ческий разбор имени файла (по схеме namei-iget), ядро обнаруживает, что файл
удаленный,  и посылает на машину, где он находится, запрос на получение заб-
локированного индекса. Получив желаемый ответ, локальное ядро создает в  па-

                                    394

мяти  копию индекса, корреспондирующую с удаленным файлом. Затем ядро произ-
водит проверку наличия необходимых прав доступа к файлу (на  чтение,  напри-
мер),  послав  на  удаленную машину еще одно сообщение. Выполнение алгоритма
open продолжается в полном соответствии с планом, приведенным в главе  5,  с
посылкой  сообщений  на  удаленную  машину по мере необходимости, до полного
окончания алгоритма и освобождения индекса.  Взаимосвязь  между  структурами
данных ядра по завершении алгоритма open показана на Рисунке 13.11.
    Если  клиент вызывает системную функцию read, ядро клиента блокирует ло-
кальный индекс, посылает запрос на блокирование удаленного  индекса,  запрос
на чтение данных, копирует данные в локальную память, посылает запрос на ос-
вобождение  удаленного  индекса  и освобождает локальный индекс. Такая схема
соответствует семантике существующего однопроцессорного ядра, но частота ис-
пользования сети (несколько обращений на каждую системную  функцию)  снижает
производительность  всей  системы. Однако, чтобы уменьшить поток сообщений в
сети, в один запрос можно объединять несколько операций. В примере с функци-
ей read клиент может послать серверу один общий запрос  на  "чтение",  а  уж
сервер при его выполнении сам принимает решение на захват и освобождение ин-
декса. Сокращения сетевого трафика можно добиться и путем использования уда-
ленных  буферов (о чем мы уже говорили выше), но при этом нужно позаботиться
о том, чтобы системные функции работы с файлами,  использующие  эти  буферы,
выполнялись надлежащим образом.
    При  второй  форме  связи с удаленной машиной (вызов удаленной системной
функции) локальное ядро обнаруживает, что системная функция имеет  отношение
к  удаленному файлу, и посылает указанные в ее вызове параметры на удаленную
систему, которая исполняет функцию и возвращает результаты  клиенту.  Машина
клиента  получает результаты выполнения функции и выходит из состояния вызо-
ва. Большинство системных функций  может  быть  выполнено  с  использованием
только одного сетевого запроса с получением ответа через достаточно приемле-
мое  время,  но в такую модель вписываются не все функции. Так, например, по
получении некоторых сигналов ядро создает для процесса файл с именем  "core"
(глава  7). Создание этого файла не связано с конкретной системной функцией,
а завершает выполнение нескольких операций, таких как создание  файла,  про-
верка прав доступа и выполнение ряда операций записи.
    В случае с системной функцией open запрос на исполнение функции, посыла-
емый на удаленную машину, включает в себя часть имени файла, оставшуюся пос-
ле исключения компонент имени пути поиска, отличающих удаленный файл, а так-
же  различные  флаги.  В  рассмотренном  ранее  примере  с  открытием  файла
"/usr/src/cmd/login.c" ядро посылает на удаленную машину имя  "cmd/login.c".
Сообщение  также включает в себя опознавательные данные, такие как пользова-
тельский и групповой коды идентификации, необходимые для проверки прав  дос-
тупа  к файлам на удаленной машине. Если с удаленной машины поступает ответ,
свидетельствующий об успешном выполнении функции open, локальное ядро  выби-
рает  свободный  индекс  в памяти локальной машины и помечает его как индекс
удаленного файла, сохраняет информацию об удаленной машине и  удаленном  ин-
дексе  и  по  заведенному  порядку выделяет новую запись в таблице файлов. В
сравнении с реальным индексом на удаленной машине индекс, принадлежащий  ло-
кальной  машине, является формальным, не нарушающим конфигурацию модели, ко-
торая в целом совпадает с конфигурацией, используемой при  вызове  удаленной
процедуры  (Рисунок  13.11).  Если вызываемая процессом функция обращается к
удаленному файлу по его дескриптору, локальное ядро узнает из  индекса  (ло-
кального)  о  том, что файл удаленный, формулирует запрос, включающий в себя
вызываемую функцию, и посылает его на удаленную машину. В запросе содержится
указатель на удаленный индекс, по которому процесс-спутник сможет  идентифи-
цировать сам удаленный файл.
    Получив результат выполнения любой системной функции, ядро может для его
обработки  прибегнуть к услугам специальной программы (по завершении которой
ядро закончит работу с функцией), ибо не всегда локальная обработка  резуль-
татов,  применяемая  в однопроцессорной системе, подходит для системы с нес-
колькими процессорами. Вследствие этого возможны изменения в семантике  сис-

                                    395

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




    Использование  передаточных  процессов (процессов-спутников) в "прозрач-
ной" распределенной системе облегчает слежение за удаленными файлами, однако
при этом таблица процессов удаленной системы перегружается  процессами-спут-
никами, бездействующими большую часть времени. В других схемах для обработки
удаленных  запросов используются специальные процессы-серверы (см. [Sandberg
85] и [Cole 85]). Удаленная  система  располагает  набором  (пулом)  процес-
сов-серверов, время от времени назначаемых ею для обработки поступающих уда-
ленных запросов. После обработки запроса процесс-сервер возвращается в пул и
переходит  в  состояние  готовности  к выполнению обработки других запросов.
Сервер не сохраняет пользовательский контекст между двумя  обращениями,  ибо
он  может  обрабатывать  запросы  сразу нескольких процессов. Следовательно,
каждое поступающее от процесса-клиента сообщение должно включать в себя  ин-
формацию  о среде его выполнения, а именно: коды идентификации пользователя,
текущий каталог, сигналы и т.д. Процессы-спутники получают эти данные в  мо-
мент своего появления или во время выполнения системной функции.
    Когда процесс открывает удаленный файл, ядро удаленной системы назначает
индекс для последующих ссылок на файл. Локальная машина располагает таблицей
пользовательских  дескрипторов  файла, таблицей файлов и таблицей индексов с
обычным набором записей, причем запись  в  таблице  индексов  идентифицирует
удаленную  машину и удаленный индекс. В тех случаях, когда системная функция
(например, read) использует дескриптор файла, ядро посылает сообщение,  ука-
зывающее  на ранее назначенный удаленный индекс, и передает связанную с про-
цессом информацию: код  идентификации  пользователя,  максимально-допустимый
размер  файла  и  т.п. Если удаленная машина имеет в своем распоряжении про-
цесс-сервер, взаимодействие с клиентом принимает вид, описанный ранее, одна-
ко связь между клиентом и сервером устанавливается только на время  выполне-
ния системной функции.
    Если  вместо  процессов-спутников воспользоваться услугами серверов, уп-
равление потоком данных, сигналами и удаленными  устройствами  может  услож-
ниться.  Поступающие в большом количестве запросы к удаленной машине при от-
сутствии достаточного числа серверов должны  выстраиваться  в  очередь.  Для
этого  нужен протокол более высокого уровня, чем тот, который используется в
основной сети. В модели, использующей спутник, с другой  стороны,  перенасы-
щенность запросами исключается, ибо все запросы клиента обрабатываются синх-
ронно. Клиент может иметь не более одного запроса, ожидающего обработки.
    Обработка  сигналов,  прерывающих  выполнение системной функции, при ис-
пользовании серверов также усложняется, поскольку удаленной машине приходит-
ся при этом искать соответствующий сервер, обслуживающий выполнение функции.
Не исключается даже и такая возможность, что в связи с занятостью всех  сер-
веров  запрос на выполнение системной функции находится в состоянии ожидания
обработки. Условия для возникновения конкуренции складываются и тогда, когда
сервер возвращает результат выполнения системной функции вызывающему процес-
су и ответ сервера заключает в себе посылку через сеть соответствующего сиг-
нального сообщения. Каждое сообщение должно  быть  помечено  таким  образом,
чтобы  удаленная система могла распознать его и в случае необходимости прер-
вать работу процессов-серверов. При использовании спутников тот процесс, ко-
торый обслуживает выполнение запроса клиента, идентифицируется  автоматичес-
ки,  и  в  случае  поступления сигнала проверка того, закончена ли обработка
запроса или нет, не составляет особого труда.
    Наконец, если вызываемая клиентом системная  функция  заставляет  сервер
приостановиться  на неопределенное время (например, при чтении данных с уда-

                                    396

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


Пользователь   +------------------------------+
     |         | Библиотека системных функций |
     |         +------------------------------+
     |         | Уровень связи типа Newcastle |
     v         +------------------------------+
     ^         +------------------------------+
     |         | Подпрограмма обработки обра- |
     |         | щения к системной функции    |
     |         +------------------------------+    + Периферийная
     |         | Подпрограмма взаимодействия с<----+ система,
     |         | удаленной файловой системой  |    | вызов удален-
     |         +------------------------------+    + ной системы
     |         | Подсистема управления файлами<------Вызов удален-
   Ядро        +------------------------------+      ной процедуры

    Рисунок 13.12.  Концептуальная схема взаимодействия с удален-
                    ными файлами на уровне ядра





    В  данной  главе нами были рассмотрены три схемы работы с расположенными
на удаленных машинах файлами, трактующие удаленные файловые системы как рас-
ширение локальной. Архитектурные различия между этими  схемами  показаны  на
Рисунке  13.12.  Все они в свою очередь отличаются от многопроцессорных сис-
тем, описанных в предыдущей главе, тем, что здесь процессоры  не  используют
физическую память совместно. Система с периферийными процессорами состоит из
сильносвязанного набора процессоров, совместно использующих файловые ресурсы
центрального  процессора.  Связь типа Newcastle обеспечивает скрытый ("проз-
рачный") доступ к удаленным файлам, но не средствами ядра операционной  сис-
темы,  а  благодаря использованию специальной Си-библиотеки. По этой причине
все программы, предполагающие использовать связь данного типа,  должны  быть
перекомпилированы, что в общем-то является серьезным недостатком этой схемы.
Удаленность файла обозначается с помощью специальной последовательности сим-
волов,  описывающих  машину,  на которой расположен файл, и это является еще
одним фактором, ограничивающим мобильность программ.
    В "прозрачных" распределенных системах для доступа  к  удаленным  файлам
используется модификация системной функции mount. Индексы в локальной систе-
ме содержат отметку о том, что они относятся к удаленным файлам, и локальное
ядро посылает на удаленную систему сообщение, описывающее запрашиваемую сис-
темную  функцию, ее параметры и удаленный индекс. Связь в "прозрачной" расп-
ределенной системе поддерживается в двух формах: в  форме  вызова  удаленной
процедуры  (на  удаленную  машину  посылается сообщение, содержащее перечень
операций, связанных с индексом) и в форме вызова удаленной системной функции
(сообщение описывает запрашиваемую функцию). В  заключительной  части  главы

                                    397

рассмотрены  вопросы, имеющие отношение к обработке дистанционных запросов с
помощью процессов-спутников и серверов.




 *1. Опишите реализацию системной функции exit  в  системе  с  периферийными
     процессорами. В чем разница между этим случаем и тем, когда процесс за-
     вершает свою работу по получении неперехваченного сигнала ? Каким обра-
     зом ядру следует сохранить дамп содержимого памяти ?
  2.  Процессы  не  могут  игнорировать сигналы типа SIGKILL; объясните, что
     происходит в периферийной системе, когда процесс получает такой сигнал.
 *3. Опишите реализацию системной функции exec  в  системе  с  периферийными
     процессорами.
 *4. Каким образом центральному процессору следует производить распределение
     процессов  между периферийными процессорами с тем, чтобы сбалансировать
     общую нагрузку ?
 *5. Что произойдет в том случае, если у периферийного процессора не окажет-
     ся достаточно памяти для размещения всех выгруженных на него процессов?
    Каким образом должны производиться выгрузка и подкачка процессов в сети?
  6. Рассмотрим систему, в которой запросы к  удаленному  файловому  серверу
     посылаются  в  случае  обнаружения в имени файла специального префикса.
     Пусть процесс вызывает функцию
               execl("/../sftig/bin/sh","sh",0);
     Исполняемый модуль находится на удаленной машине, но должен выполняться
     в локальной системе. Объясните, каким образом удаленный модуль  перено-
     сится в локальную систему.
  7. Если администратору нужно добавить в существующую систему со связью ти-
     па  Newcastle новые машины, то как об этом лучше всего проинформировать
     модули Си-библиотеки ?
 *8. Во время выполнения функции exec ядро  затирает  адресное  пространство
     процесса,  включая  и  библиотечные  таблицы,  используемые связью типа
     Newcastle для слежения за ссылками на удаленные файлы. После выполнения
     функции процесс должен сохранить возможность обращения к этим файлам по
     их старым дескрипторам. Опишите реализацию этого момента.
 *9. Как показано в разделе 13.2, вызов системной функции exit в системах со
     связью типа Newcastle приводит к посылке  сообщения  процессу-спутнику,
     заставляющего  последний  завершить свою работу. Это делается на уровне
     библиотечных подпрограмм. Что происходит, когда локальный процесс полу-
     чает сигнал, побуждающий его завершить свою работу в режиме ядра ?
*10. Каким образом в системе со связью типа Newcastle, где  удаленные  файлы
     идентифицируются  добавлением  к имени специального префикса, пользова-
     тель может, указав в качестве компоненты имени файла ".." (родительский
     каталог), пересечь удаленную точку монтирования ?
 11. Из главы 7 нам известно о том, что различные сигналы побуждают  процесс
     сбрасывать  дамп содержимого памяти в текущий каталог. Что должно прои-
     зойти в том случае, если текущим является каталог из удаленной файловой
     системы ? Какой ответ вы дадите в том случае, если в системе  использу-
     ется связь типа Newcastle ?
*12.  Какие последствия для локальных процессов имело бы удаление из системы
     всех процессов-спутников или серверов ?
*13. Подумайте над тем, как в "прозрачной"  распределенной  системе  следует
     реализовать  алгоритм  link,  параметрами которого могут быть два имени
     удаленных файлов, а также алгоритм exec, связанный с  выполнением  нес-
     кольких  внутренних операций чтения. Рассмотрите две формы связи: вызов
     удаленной процедуры и вызов удаленной системной функции.
*14. При обращении к устройству процесс-сервер  может  перейти  в  состояние
     приостанова, из которого он будет выведен драйвером устройства. Естест-
     венно,  если  число серверов ограничено, система не сможет больше удов-

                                    398

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

          +----------+    +----------+     +----------+
          | Клиент A |    | Клиент B |     | Клиент C |
          +----------+    +----------+     +----------+
             -    -          -    -           -    -
     getty-  -    -          -    -           -    -
     процессы-    -          -    -           -    -
             -    -          -    -           -    -
          +-------------------------------------------+ терминаль-
          |  -    -          -    -           -    -  | ный сервер
          +--+----+----------+----+-----------+----+--+
             |    |          |    |           |    |
          tty00  tty01    tty02  tty03     tty04  tty05

         Рисунок 13.13. Конфигурация с терминальным сервером

*15. Когда пользователь регистрируется в  системе,  дисциплина  терминальной
     линии  сохраняет  информацию о том, что терминал является операторским,
     ведущим группу процессов. По этой причине, когда пользователь на клави-
     атуре терминала нажимает клавишу "break",  сигнал  прерывания  получают
     все  процессы  группы.  Рассмотрим  конфигурацию системы, в которой все
     терминалы физически подключаются к одной машине, но регистрация пользо-
     вателей логически реализуется на других машинах (Рисунок 13.13). В каж-
     дом  отдельном  случае  система  создает   для   удаленного   терминала
     getty-процесс.  Если  запросы  к удаленной системе обрабатываются с по-
     мощью набора процессов-серверов, следует отметить, что  при  выполнении
     процедуры открытия сервер останавливается в ожидании подключения. Когда
     выполнение функции open завершается, сервер возвращается обратно в сер-
     верный пул, разрывая свою связь с терминалом. Каким образом осуществля-
     ется  рассылка  сигнала  о  прерывании,  вызываемого  нажатием  клавиши
     "break", по адресам процессов, входящих в одну группу ?
*16. Разделение памяти - это особенность, присущая локальным машинам. С  ло-
     гической  точки  зрения, выделение общей области физической памяти (ло-
     кальной или удаленной) можно осуществить и для процессов, принадлежащих
     разным машинам. Опишите реализацию этого момента.
*17. Рассмотренные в главе 9 алгоритмы выгрузки процессов и подкачки страниц
     по обращению предполагают использование локального устройства выгрузки.
     Какие изменения следует внести в эти алгоритмы для того, чтобы  создать
     возможность поддержки удаленных устройств выгрузки ?
*18.  Предположим,  что  на удаленной машине (или в сети) случился фатальный
     сбой и локальный протокол сетевого уровня зафиксировал этот факт.  Раз-
     работайте  схему  восстановления локальной системы, обращающейся к уда-
     ленному серверу с запросами. Кроме того, разработайте схему  восстанов-
     ления серверной системы, утратившей связь с клиентами.
*19.  Когда  процесс обращается к удаленному файлу, не исключена возможность
     того, что в поисках файла процесс обойдет несколько машин.  В  качестве
     примера  возьмем  имя "/usr/src/uts/3b2/os", где "/usr" - каталог, при-
     надлежащий машине A, "/usr/src" - точка монтирования  корня  машины  B,
     "/usr/src/uts/3b2"  -  точка  монтирования корня машины C. Проход через
     несколько машин к месту конечного назначения называется "мультискачком"
     (multihop). Однако, если между машинами A и C существует непосредствен-
     ная сетевая связь, пересылка данных через машину B была бы  неэффектив-
     ной.  Опишите особенности реализации "мультискачка" в системе со связью
     Newcastle и в "прозрачной" распределенной системе.


                                    399

Популярность: 1, Last-modified: Thu, 12 Feb 1998 07:20:51 GmT