Что такое распределенная система?

Перед тем, как ответить на вопрос, что я знаю о распределенных операционных системах, я должен объяснить, что я понимаю под этими словами. Как только термин "распределенная система" сделался популярным, кое-кто из производителей объявил, что он уже имеет для продажи распределенную систему, состоящую из большого компьютера, к которому можно подсоединить сотни АЦ-терминалов. Это не совсем то, что я имею в виду.

На мой взгляд, распределенная система имеет две существенные характеристики:

  • система состоит из нескольких независимых, автономных, взаимодействующих процессоров
  • система воспринимается пользователями как один компьютер

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

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

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

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

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

В настоящий момент мало распределенных компьютерных систем доступно коммерчески, но в 90-е годы они станут намного многочисленнее. Несколько различных прототипов сейчас разрабатываются в лабораториях. Большая часть наших знаний об обсуждаемой проблеме - именно из этих экспериментальных систем. Возможно, стоит сказать прямо: распределенную систему не просто спроектировать и запрограммировать - иначе бы они коммерчески использовались значительно шире. Трудоемкость разработки распределенных систем подталкивает к использованию методов, упрощающих, насколько возможно, их создание. О таких методах и пойдет речь ниже.

Структура системы

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

Наблюдение 1: Распределенные системы должны основываться на микроядрах.

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

Микроядра появились сравнительно недавно, хотя некоторые идеи можно было найти у Бринч Хансена еще 20 лет назад в системе RC 4000. Хорошо известные примеры микроядер: Amoeba [Tan90a], Chorus [Roz88a], Mach [You87a], V [Che88a].

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

Микроядра обычно выполняют следующие функции:

  • межпроцессное взаимодействие
  • нижнеуровневое упраление процессами
  • нижнеуровневое управление памятью
  • ввод/вывод

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

Так как процессы в распределенной системе могут выполняться на разъединенных компьютерах, межпроцессорное взаимодействие на нижнем уровне надо строить на передаче сообщений. Микроядро должно представлять примитивы для посылки и приема сообщений. Возможны различные опции, включая синхронность/асинхронность, надежность/ненадежность, наличие или отсутствие блокировок и буферизации, двухточечное/групповое взаимодействие. У каждой комбинации свои свойства.

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

Управление памятью - это тоже функция микроядра, по крайней мере отчасти: MMU надо проинициализировать, ошибки из-за отсутствия страниц надо обрабатывать. В то же время часть работы можно сделать вне ядра, как в Mach.

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

Очевидна аналогия между микроядрами и RISC-машинами. У RISC-машин меньше команд, чем у CISC-машин. Руководящий принцип проектирования RISC: если без команды можно обойтись, от нее отказываются. В значительной мере это верно и для микроядер: если можно какую-то функцию обеспечить вне ядра, она из ядра изымается. Коротко говоря, микроядра можно назвать операционными системами типа RISC.

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

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

С модульностью тесно связано и третье преимущество - гибкость. Одно и то же микроядро может использоваться как база для различных ОС. Mach одновременно выполняет и Unix и MS-Dos. Микроядра удобны и пользователям со специфическими нуждами (например, разработчикам баз данных) - они могут реализовать собственные файловые системы. В "монолитной" ОС Вам не отделаться от навязываемой файловой системы; это иногда превращается в серьезную проблему [Sto81a].

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

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

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

Наблюдение 2. Следует использовать модель клиент-сервер.

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

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

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

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

Модель клиент-сервер, напротив, основана на абстрактных типах данных (объектах). Сервер может предоставить объекты произвольной природы и необходимый набор операций для них, инкапсулируя объекты и позволяя выполнять над ними только предусмотренные действия. Данная парадигма обеспечивает упрятывание информации и облегчает конструирование корректных и доступных для понимания программ.

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

Наблюдение 3. Unix вполне может исполняться как прикладная программа.

Из идеи о том, что ОС надо строить на микроядре, над которым выполняются процессы-серверы, следует, что Unix (MS Dos ил другая ОС) должна выполняться как приложение. В существующих распределенных системах можно обнаружить два различных подхода; оба кажутся удовлетворительными.

Первый подход используется, если требуется двоичная совместимость, для выполнения программ, исходный текст которых недоступен. Один из способом добиться двоичной совместимости состоит в том, чтобы отобразить (разделяемую) библиотеку эмуляции на верхнюю часть адресного пространства всех Unix-процессов. Когда процесс делает системный вызов, микроядро его перехватывает и возвращает управление обработчику внутри библиотеки эмуляции. Библиотека затем обращается к Unix-серверу, который и делает необходимую работу. Этого пути придерживаются Mach и Chorus.

Другой подход - предоставить библиотеку системных вызовов Unix (open, read и т.д.) и перекомпилировать с ней существующие программы. Это самый эффективный способ, так как он избавлен от накладных расходов на прерывания эмуляции; он выбран в Amoeba.

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

Наблюдение 4: Хорошая модель взаимодействия - вызов удаленной процедуры.

Модель клиент-сервер определяет общую картину взаимодействия процессов, но оставляет открытым вопрос о том, какими должны быть примитивы взаимодействия. В своей, ставшей классической, работе Бирелл и Нельсон показали, что можно вообще скрыть взаимодействие при помощи единственной абстракции - давно известного вызова процедуры [Bir84a]. Эта техника известна как вызов удаленной процедуры (RCP - Remote Pricedure Call) и широко используется в распределенных ОС.

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

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

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

RPC имеет и отдельные недостатки. Для искушенного программиста при разработке специального, требующего более сложного взаимодействия приложения RPC может оказаться слишком ограничительным. Иногда утверждают, что достаточно примитивов SEND и RECIEVE, как для тех, кто хочет сконструировать из них RPC, так и для тех, кто будет использовать их непосредственно. Это напоминает разговоры о том, что язык программирования должен предоставлять только операторы IF и GOTO, поскольку циклы FOR и WHILE через них выразимы. Этот аргумент обманчив. При разработке сложных программных систем существенно, чтобы были доступны высокоуровневые примитивы, а не низкоуровневые ( в надежде на то, что программисты не будут ими злоупотреблять). В приложениях, для которых совсем не подходит синхронное взаимодействие, следует использовать несколько нитей управления.

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

Наблюдение 5: Надо использовать глобально упорядоченное, надежное широковещание.

Распределенную систему можно конструировать и использовать по разному. Если доступно большое число процессоров, разрозненных рабочих станций или сосредоточенных в машинном зале компьютеров, их можно объединить для совместной работы в параллель, чтобы ускорить отдельно взятое приложение. И напротив, систему можно спроектировать подобным образом с самого начала. Для определенных приложений взаимодействие типа клиент-сервер вообще не подходит. Часто имеет место взаимодействие одного процесса со многими (то есть широковещание). Хотя широковещание можно промоделировать при многократных RPC, это слишком неэффективно. Более того, если одновременно несколько процессов вступает во взаимодействие один-к-многим, сообщения могут перемешаться, а могут и возникнуть ошибки.

Рассмотрим, например, простую СУБД, копирующую свои данные на несколько машин, что позволяет каждому делать запросы одновременно со другими. Чтения - это локальные операции, но когда запись изменяется, ее надо обновить одновременно на всех машинах, чтобы избежать несоответствий. Другой пример - разделяемые структуры данных, доступные на чтение и запись многим компьютерам. В такой ситуации был бы полезен базовый примитив, позволяющий "широковещать" сообщение всем машинам надежным и неделимым образом.

Различные распределенные системы, начиная с V и ISIS [Che88a, Bir91a], поддерживают широковещание в разнообразных формах. Опыт Amoeba показывает, что наличие надежного, неделимого, глобального упорядоченного широковещания как базового примитива значительно облегчает параллельного программирования распределенных систем (в том числе и отказоустойчивое). Необходимы два ключевых свойства:

  • любое сообщение получают все заинтересованные процессы или ни один из них
  • все процессы получают все сообщения в одном и том же порядке

Используя широковещание, можно обновить переменную во всех процессах сразу, не заботясь о потерянных или перемешавшихся сообщениях и других проблемах. Данный механизм можно применять и для конструирования еще более удобных в использовании абстракций, например, разделяемых объектов данных [Bal91a]. Без транслирования программирование таких приложений намного осложняется.

Наблюдение 6: Взаимодействие должно быть прозрачным.

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

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

Распределенная разделяемая память

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

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

Наблюдение 7: Распределенная разделяемая память облегчает параллельное программирование.

Распределенная разделяемая память имеет две разновидности: основанная на страницах и основанная на объектах. Пионерами первого варианта были Ли и Гудак [Li89a]. Он действует как система со сквозной страничной организацией памяти всех машин, разделяющих общее виртуальное адресное пространство. Страницы при необходимости самостоятельно передаются между машинами. Когда просходит прерывание из-за отсутствия страницы, необходимая страница извлекается из машины, которая ее в настоящий момент содержит. Страницы, доступные только для чтения, можно дублировать , однако страницы, доступные и для записи, надо удалять с предыдущего места хранения, поскольку они не могут существовать на двух машинах одновременно.

В распределенной разделяемой памяти, основанной на объектах, единицы разделения задаются программными объектами [Bal92a, Car89a, Jul88a]. Над объектами определяются операции, и когда эти операции над объектом выполняются, они сами делают объект доступным.

В обоих случаях для программиста на мультикомпьютерах создается иллюзия разделяемой памяти. Процессы на различных машинах могут использовать разделяемую память для взаимодействия и синхронизации, что обычно намного удобнее передачи сообщений. В Amoeba основанная на объектах разделяемая память реализуется копированием объектов на все машины, локальными операциями чтения и операциями записи на базе глобально упорядоченного широковещания [Tan92a]. Конечно, возможны и другие методы реализации.

Открытые проблемы

Многие проблемы все еще открыты. Здесь я коротко упомяну некоторые идеи; надеюсь, мы сумеем понять, какие из них хороши, а какие - нет.

Принадлежность машины

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

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

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

Использование кэша для файлов

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

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

Нити управления

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

Атомарные транзакции

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

Заключение

Подводя итог, можно сказать: главное, чему я научился, состоит в том, что спроектировать и реализовать распределенную ОС не так легко, как кажется. Необходимо избегать сложностей, где это возможно, и сопротивляться соблазну добавить дополнительные функции. Фокус в том, чтобы найти простые концептуальные модели, а не пытаться сделать все для всех. Вдохновение же следует черпать в Unix, а не в ОС/360. Если каждый разработчик выберет себе старый лозунг Будь проще! мы будем двигаться вперед быстрее.

Литература

[And91a] T. E. Anderson, B. N. Bershad, E. D. Lazovska, and H. M. Levy, "Scheduler Activations: Effective Kernel Support for the User-Level", Management of Parallelism - Proc. Thirteenth Symposium on Operating System Principles, Pacific Grove, CA, pp.95-109 (14-16 Oct.1991).

[Bal91a] H. E. Bal and A. S. Tanenbaum, "Distributed Programming with Shared Data", Computer Languages 16(2), pp.129-146(1991).

[Bal92a] H. E. Bal, M. F. Kaashoek, and A. S. Tanenbaum, "Ocra: A language for Parallel Programming of Distributed Systems", IEEE Transactions of Software Engeneering, pp.190-205 (March 1992).

[Bir91a] K. Birman, A. Schiper, and P. Stephenson, "Lightweight Causal and Atomic Gruop Multicast", ACM Trans. Comp. Syst. 9(3), pp.272-314 (Aug. 1991).

[Bir84a] A. D. Birrel and B. J. Nelson, "Implementing Remote Procedure Calls", ACM Trans. Computer Systems 2, pp.39-59 (Feb. 1984).

[Car89a] N. Carriero and D. Gelernter, "Linda in Context", Commun. ACM 32(4), pp.444-458 (April 1989).

[Che88a] D. R. Cheriton, "The V Distributed System", Commun. of the ACM 31, pp.314-333 (March 1988).

[Gol90a] D. Golub, R. Dean, A. Forin, and R. Rashid, "Unix as an application program", USENIX Summer Conf., Anaheim, CA, pp.87-95 (June 1990).

[Han73a] P. Brinch Hansen, Operating System Principles, Prentice Hall, Englewood Cliffs, NJ (1973).

[Jul88a] E. Jul, H. Levy, N. Hatchinson, and A. Black, "FineGrained Mobility in the Emerald Sistem", ACM Trans. on Computer Systems 6, pp.109-113 (Feb. 1988).

[Li89a] K. Li and P. Hudak, "Memory Coherehce in Shared Virtual Memory Systems", ACM Trans. Comp. Syst. 7(4), pp.321-359 (Nov. 1989).

[Roz88a] M. Rozier, V. Abrossimov, F. Armand, I. Boule, M. Gien, M. Guillemont, F. Herrmann, C. Kaiser, S. Langlois, P. Leonard, and W. Neuhauser, "CHORUS Distributed Operating Systems", Computing Systems 1 (1988).

[Sto81a] M. Stonebraker, "Operating System Support for Database Management", Commun. of the ACM 24, pp.412-418 (July 1981).

[Tan90a] A. S. Tanenbaum, R. van Renesse, H. van Staveren, G. J. Sharp, S. J. Mullender, J. Jansen, and G. van Rossum, "Experiences with Amoeba Distributed Operating System", Commun. of the ACM 33, pp.46-63 (Dec. 1990).

[Tan92a] A. S. Tanenbaum, M. F. Kaashoek, and H. E. Bal, "Parallel Progpamming Using Shared Objects And Broadcasting", Computer 25 (Aug. 1992).

[You87a] M. Young, A. Teverian, R. Rashid, D. Golub, J. Eppinger, J. Chew, W. Bolosky, D. Black, and R. Baron, "Duality of Memory and Communication in the Implementation of a Multiprocessor Operating System", Proc. Eleventh ACM Symposium on Operating Systems Principles, Austin, TX, pp.63-67 (Nov. 1987).