ГЛАВА 13. РАСПРЕДЕЛЕННЫЕ СИСТЕМЫ В предыдущей главе нами были рассмотрены сильносвязанные многопроцессор- ные системы с общей памятью, общими структурами данных ядра и общим пулом, из которого процессы вызываются на выполнение. Часто, однако, бывает жела- тельно в целях обеспечения совместного использования ресурсов распределять процессоры таким образом, чтобы они были автономны от операционной среды и условий эксплуатации. Пусть, например, пользователю персональной ЭВМ нужно обратиться к файлам, находящимся на более крупной машине, но сохранить при этом контроль над персональной ЭВМ. Несмотря на то, что отдельные программы, такие как uucp, поддерживают передачу файлов по сети и другие сетевые функ- ции, их использование не будет скрыто от пользователя, поскольку пользова- тель знает о том, что он работает в сети. Кроме того, надо заметить, что программы, подобные текстовым редакторам, с удаленными файлами, как с обыч- ными, не работают. Пользователи должны располагать стандартным набором функ- ций системы UNIX и, за исключением возможной потери в быстродействии, не должны ощущать пересечения машинных границ. Так, например, работа системных функций open и read с файлами на удаленных машинах не должна отличаться от их работы с файлами, принадлежащими локальным системам. Архитектура распределенной системы представлена на Рисунке 13.1. Каждый компьютер, показанный на рисунке, является автономным модулем, состоящим из ЦП, памяти и периферийных устройств. Соответствие модели не нарушается даже несмотря на то, что компьютер не располагает локальной файловой системой: он должен иметь периферийные устройства для связи с другими машинами, а все принадлежащие ему файлы могут располагаться и на ином компьютере. Физическая память, доступная каждой машине, не зависит от процессов, выполняемых на других машинах. Этой особенностью распределенные системы отличаются от силь- носвязанных многопроцессорных систем, рассмотренных в предыдущей главе. Со- ответственно, и ядро +-----------------------------+ +-----------------------------+ | +------------+ | | +------------+ | | | Процессоры | | | | Процессоры | | | +-----+------+ | | +-----+------+ | | ----+-------+------+------- | | ----+-------+------+------- | | +---+----+ +-------+------+ | | +---+----+ +-------+------+ | | | Память | | Периферийные | | | | Память | | Периферийные | | | | | | устройства | | | | | | устройства | | | +--------+ +--------------+ +-++-+ +--------+ +--------------+ | +-----------------------------+ ++ +-----------------------------+ | +-------------+---------------+ | +------------+ | | | Процессоры | | | +-----+------+ | | ----+-------+------+------- | | +---+----+ +-------+------+ | | | Память | | Периферийные | | | | | | устройства | | | +--------+ +--------------+ | +-----------------------------+ Рисунок 13.1. Модель системы с распределенной архитектурой 381 системы на каждой машине функционирует независимо от внешних условий эксплу- атации распределенной среды. Распределенные системы, хорошо описанные в литературе, традиционно де- лятся на следующие категории: * периферийные системы, представляющие собой группы машин, отличающихся ярковыраженной общностью и связанных с одной (обычно более крупной) ма- шиной. Периферийные процессоры делят свою нагрузку с центральным процес- сором и переадресовывают ему все обращения к операционной системе. Цель периферийной системы состоит в увеличении общей производительности сети и в предоставлении возможности выделения процессора одному процессу в операционной среде UNIX. Система запускается как отдельный модуль; в от- личие от других моделей распределенных систем, периферийные системы не обладают реальной автономией, за исключением случаев, связанных с дис- петчеризацией процессов и распределением локальной памяти. * распределенные системы типа "Newcastle", позволяющие осуществлять дис- танционную связь по именам удаленных файлов в библиотеке (название взято из статьи "The Newcastle Connection" - см. [Brownbridge 82]). Удаленные файлы имеют спецификацию (составное имя), которая в указании пути поиска содержит специальные символы или дополнительную компоненту имени, пред- шествующую корню файловой системы. Реализация этого метода не предпола- гает внесения изменений в ядро системы, вследствие этого он более прост, чем другие методы, рассматриваемые в этой главе, но менее гибок. * абсолютно "прозрачные" распределенные системы, в которых для обращения к файлам, расположенным на других машинах, достаточно указания их стандар- тных составных имен; распознавание этих файлов как удаленных входит в обязанности ядра. Маршруты поиска файлов, указанные в их составных име- нах, пересекают машинные границы в точках монтирования, сколько бы таких точек ни было сформировано при монтировании файловых систем на дисках. В настоящей главе мы рассмотрим архитектуру каждой модели; все приводи- мые сведения базируются не на результатах конкретных разработок, а на инфор- мации, публиковавшейся в различных технических статьях. При этом предполага- ется, что забота об адресации, маршрутизации, управлении потоками, обнаруже- нии и исправлении ошибок возлагается на модули протоколов и драйверы устрой- ств, другими словами, что каждая модель не зависит от используемой сети. Примеры использования системных функций, приводимые в следующем разделе для периферийных систем, работают аналогичным образом и для систем типа Newcastle и для абсолютно "прозрачных" систем, о которых пойдет речь позже; поэтому в деталях мы их рассмотрим один раз, а в разделах, посвященных дру- гим типам систем, остановимся в основном на особенностях, отличающих эти мо- дели от всех остальных. 13.1 ПЕРИФЕРИЙНЫЕ ПРОЦЕССОРЫ Архитектура периферийной системы показана на Рисунке 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 13.2 СВЯЗЬ ТИПА NEWCASTLЕ В предыдущем разделе мы рассмотрели тип сильносвязанной системы, для ко- торого характерна посылка всех возникающих на периферийном процессоре обра- щений к функциям подсистемы управления файлами на удаленный (центральный) процессор. Теперь перейдем к рассмотрению систем с менее сильной связью, ко- торые состоят из машин, производящих обращение к файлам, находящимся на дру- гих машинах. В сети, состоящей из персональных компьютеров и рабочих стан- ций, например, пользователи часто обращаются к файлам, расположенным на большой машине. В последующих двух разделах мы рассмотрим такие конфигурации систем, в которых все системные функции выполняются в локальных подсистемах, но при этом имеется возможность обращения к файлам (через функции подсистемы управления файлами), расположенным на других машинах. Для идентифицирования удаленных файлов в этих системах используется один из следующих двух путей. В одних системах в составное имя файла добавляется специальный символ: компонента имени, предшествующая этому символу, иденти- фицирует машину, остальная часть имени - файл, находящийся на этой машине. Так, например, составное имя "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 в сторону расширения ее возможностей в автоматическом установлении всех необходимых пользо