Искусство программирования для Unix

Реймонд Эрик Стивен

 

ISBN 5-8459-0791-8 (рус.)

 

Вдохновившим меня Кену Томпсону и Деннису Ритчи

 

Предисловие

 

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

Целью книги является попытка преподнести читателям аспекты разработки программ в Unix, которые интуитивно известны экспертам данной операционной системы. Поэтому в данной книге, в отличие от большинства других книг о Unix, рассматривается меньше технических подробностей и больше вопросов коллективной культуры, как в явной, так и в скрытой ее формах, а также ее осознанные и неосознанные традиции. Данная книга не дает ответов на вопросы о том, "как сделать что-либо", она не является сборником документов how-to, скорее в ней собраны ответы на вопросы наподобие "почему это следует сделать" (why-to).

Подход why-to обладает большой практической важностью, поскольку слишком многие программы проектируются неудачно. Для большинства из них характерен большой размер, чрезвычайная сложность сопровождения и чрезмерные трудности при переносе на новые платформы или расширении, которое не было предусмотрено создавшими их программистами. Данные проблемы являются симптомами ошибочного проектирования. Авторы надеются, что эта книга позволит популяризировать некоторые относящиеся к Unix знания в области хорошего проектирования.

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

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

Используя слово "мы", автор не пытается показаться всеведущим, а старается отразить тот факт, что в книге предпринята попытка ясного выражения опыта всего сообщества.

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

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

Кроме того, настоящая книга не является ни сборником уроков по языку С, ни руководством по командам и API-функциям операционной системы Unix. Она также не является справочником по программам sed или уасс, языкам Perl или Python, букварем для сетевого программиста или исчерпывающим описанием секретов системы X. Это не экскурс во внутреннее устройство или структуру операционной системы Unix. Указанные вопросы лучше рассмотрены в других книгах, и в тексте данной книги в соответствующих случаях имеются ссылки на них.

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

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

 

Для кого предназначена эта книга

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

Книгу стоит прочесть программистам на С, С++ или Java, имеющим опыт работы в других операционных системах и планирующим начать Unix-проект.

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

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

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

В то же время читателям не стоит искать здесь подробности программирования на языке С или использования API-интерфейса ядра Unix. По этим темам имеется множество хороших книг, в частности: "Advanced Programming in the Unix Environment" [81] — классический труд по изучению Unix API, а также книга "The Practice of Programming" [40J, которая входит в перечень рекомендованной литературы для всех программистов на языке С (а в действительности рекомендуется всем программистам на всех языках).

 

Как использовать эту книгу

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

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

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

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

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

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

Ссылки на дополнительную литературу обычно выполняются по номеру книги в списке (см. приложение В). Также даны нумерованные сноски на URL-адреса, которые могут затруднять чтение или предположительно являются ненадежными. Это же относится к примечаниям, историческим фактам и шуткам.

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

 

Дополнительные источники информации

Конечно, тематика данной книги уже рассматривалась в некоторых периодических изданиях и нескольких книгах, написанных первыми разработчиками операционной системы Unix. Среди них выделяется и по праву считается классической книга "The Unix Programming Environment" [39] Кернигана (Kernighan) и Пайка (Pike). Однако в ней не рассматривается Internet и World Wide Web или новая волна интерпретируемых языков программирования, таких как Perl, Tel и Python.

Работая над этой книгой, авторы внимательно изучали работу "The Unix Philosophy" [26] Майка Ганкарза (Mike Gancarz). Данная книга является выдающейся в своем роде, однако Ганкарз не пытается раскрыть полный спектр тем, которые следовало бы рассмотреть. Тем не менее, авторы выражают благодарность ее создателю за напоминание о том, что простейшие модели проектирования в Unix являются наиболее устойчивыми и удачными.

Книга "The Pragmatic Programmer" [37] отражает остроумную дискуссию о хорошей практике проектирования, которая относится к несколько другому, по сравнению с данной книгой, уровню искусства проектирования программ (в ней более подробно рассматриваются вопросы кодирования и меньше проблемы более высокого уровня). Философия ее автора базируется на опыте работы с Unix, а книга представляется отличным дополнением к данному изданию.

В книге "The Practice of Programming" [40] рассматривается несколько тех же положений, что и в книге "The Pragmatic Programmer", но в аспекте Unix-традиции.

Наконец, авторы рекомендуют "Zen Flesh, Zen Bones" [68], важную коллекцию основных источников Дзэн-буддиста. Ссылки на Дзэн включены в данную книгу, поскольку Дзэн предоставляет словарный запас для обозначения некоторых идей, которые оказываются весьма важными при проектировании программного обеспечения, но очень трудны для запоминания.

 

Соглашения, используемые в данной книге

Термин "UNIX" технически и юридически является торговой маркой организации "The Open Group", и формально он должен использоваться только относительно сертифицированных операционных систем, прошедших сложные тесты на соответствие стандартам "The Open Group". В данной книге термин "Unix" используется в более свободном, широко распространенном среди программистов смысле. Здесь термин "Unix" применяется для обозначения любой операционной системы (имеющей формальное название Unix или нет), которая либо происходит из кода, унаследованного от системы Unix компании Bell Labs, либо "написана в строгом приближении к потомкам этой системы". В частности, Linux (из которой взято большинство примеров книги), согласно данному определению, является Unix-системой.

В настоящей книге используются соглашения справочной системы Unix (manual page) для выделения средств Unix с последующим указанием в скобках номера раздела справочной системы. Обычно это делается при первом упоминании команды, если требуется показать, что она принадлежит Unix. Например, запись "munger(l)" следует читать как "программа munger, описанная в разделе 1 (пользовательские средства) справочной системы Unix, в случае если она присутствует в данной системе". Раздел 2 содержит справочные сведения о системных вызовах С, раздел 3 — о вызовах библиотеки С, раздел 5 посвящен форматам файлов и протоколам, в разделе 8 описаны средства системного администрирования. Другие разделы отличаются в зависимости от принадлежности к различным Unix-системам, но они не цитируются в данной книге. Для получения более подробных сведений следует в приглашении командной строки Unix ввести команду man 1 man (в более давних системах ветви System V Unix может потребоваться команда man -si man).

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

Далее в настоящей книге нередко встречается ссылка на методы "старой школы" и "новой школы". Подобно рэп-музыке, новая школа возникла в 90-х годах прошлого века. В данном контексте новая школа связана с появлением языков написания сценариев (scripting language), графических пользовательских интерфейсов (Graphical User Interfaces— GUI), Unix-систем с открытым исходным кодом и Web-среды. Упоминание старой школы относится к периоду до 1990 года (и особенно до 1985 года), когда повсеместно применялись дорогостоящие (совместно используемые) компьютеры, частные Unix-системы, сценарии командного интерпретатора и программы на языке С. Данные различия стоит подчеркнуть, поскольку более дешевые машины с меньшими ограничениями памяти внесли значительные изменения в стиль Unix-программирования.

 

Учебные примеры

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

cdrtools/xcdroast

Данные отдельные проекты обычно используются вместе. Пакет cdrtools представляет собой набор CLI-инструментов для записи дисков CD-ROM. Информацию по данному пакету можно найти в Web с помощью поискового слова "cdrtools". Приложение xcdroast — GUI-интерфейс для пакета cdrtools. Сайт проекта xcdroast доступен по адресу .

fetchmail

Программа fetchmail получает почту с удаленных почтовых серверов с помощью почтовых протоколов РОРЗ или IMAP. См. домашнюю страницу fetch-mail (поиск в Web с помощью ключевого слова "fetchmail").

GIMP

GIMP (GNU Image Manipulation Program — GNU-программа для работы с графическими изображениями) полнофункциональная программа для создания и обработки изображений, которая способна осуществлять сложное редактирование множества различных графических форматов. Исходные коды программы доступны на домашней странице GIMP (или поиск в Web по слову "GIMP").

mutt

Пользовательский почтовый агент mutt является лучшим среди современных текстовых Unix-агентов электронной почты, который известен благодаря хорошей поддержке MIME-форматов (Multipurpose Internet Mail Extensions — многоцелевые расширения почтового стандарта в Internet) и использованию таких средств безопасности, как PGP (Pretty Good Privacy) и GPG (GNU Privacy Guard). Исходный код продукта и исполняемые двоичные файлы доступны на сайте проекта Mutt .

xmlto

Команда xmlto преобразует DocBook-документы и другие XML-документы в различные форматы, включая HTML, текстовый формат и PostScript. Исходные коды и документация представлены на сайте проекта xmlto .

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

 

Авторские благодарности

Приглашенные помощники Кен Арнольд (Ken Arnold), Стивен М. Белловин (Steven М. Bellovin), Стюарт Фельдман (Stuart Feldman), Джим Геттис (Jim Gettys), Стив Джонсон (Steve Johnson), Брайан Керниган (Brian Kernighan), Дэвид Корн (David Кот), Майк Леек (Mike Lesk), Дуг Макилрой (Doug Mcllroy), Маршал Кирк Маккьюзик (Marshall Kirk McKusick), Кит Паккард (Keith Packard), Генри Спенсер (Henry Spencer) и Кен Томпсон (Ken Thompson) внесли крупный вклад в создание данной книги. В частности, Дуг Макилрой в очередной раз продемонстрировал свою преданность идеям превосходного качества, которые он привнес в управление еще первой исследовательской группой Unix тридцать лет назад.

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

В данную книгу вошли полезные моменты, выявленные в ходе обсуждения с другими специалистами в течение пяти лет ее написания. Марк М. Миллер (Mark М. Miller) способствовал автору в освещении темы параллельных процессов. Джон Коуэн (John Cowan) дал несколько ценных рекомендаций, касающихся моделей проектирования интерфейсов и создал черновики учебных примеров программы wily и системы VM/CMS. Джеф Раскин (Jef Raskin) продемонстрировал происхождение правила наименьшей неожиданности. Группа системной архитектуры UIUC (UIUC System Architecture Group) также внесла свои полезные дополнения. Рецензия членов группы вдохновила автора на написание разделов "Что в Unix делается неверно" и "Гибкость на всех уровнях". Рассел Дж. Нельсон (Russell J. Nelson) дополнил материал по образованию цепей Бернштайна в главе 7. Джей Мэйнард (Jay Maynard) значительно помог в разработке учебных примеров MVS в главе 3. Лес Хаттон (Les Hatton) предоставил множество полезных комментариев, касающихся главы "Языки программирования: С или не С?" и побудил автора к созданию раздела "Инкапсуляция и оптимальный размер модуля" в главе 4. Дэвид А. Вилер (David А. Wheeler) внес множество проницательных критических замечаний и некоторые материалы по учебным примерам, особенно в части "Проектирование". Расс Кокс (Russ Сох) помог развить обзор системы Plan 9. Деннис Ритчи (Dennis Ritchie) корректировал некоторые исторические моменты, касающиеся языка С.

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

На стиль изложения и некоторые вопросы, рассмотренные в данной книге, оказала определенное влияние известная концепция о моделях проектирования. Действительно, автор размышлял над названием "Модели проектирования в Unix" (Unix Design Patterns). Однако оно было отклонено, поскольку автор был не согласен с некоторыми безоговорочными догмами данной школы и не испытывал необходимости использовать весь его формальный аппарат или принимать культурный багаж. Тем не менее, работы1 Кристофера Александера (Christopher Alexander) (особенно "The Timeless Way of Building" и "A Pattern Language") оказали свое влияние на авторский подход. Автор считает своим долгом выразить огромную благодарность Группе четырех (Gang of Four) и другим членам их школы за демонстрацию того, каким образом можно использовать работы Александра в отношении проектирования на высоком уровне, не оперируя полностью неясными и бесполезными общими фразами. Заинтересованным читателям в качестве введения в тему моделей проектирования рекомендуется изучить книгу "Design Patterns: Elements of Reusable Object-Oriented Software" [24].

Название данной книги, несомненно, ассоциируется с "Искусством программирования" Дональда Кнута (Donald Knuth). Несмотря на то, что Кнут не связан с традициями Unix, он оказывает влияние на всех нас.

Редакторы с глубоким видением текста и богатым воображением встречаются не так часто, как хотелось бы. Один из них — Марк Тауб (Mark Taub), который смог оценить достоинства приостановленного проекта и деликатно подтолкнул автора к окончанию работы. Хорошим чувством прозаического стиля и достаточными способностями улучшить написанное отличается и Мэри Лау Hop (Mary Lou Nohr). Джерри Вотта Oerry Votta) уловил авторскую идею обложки и сделал ее лучше, чем можно было представить. Весь коллектив издательства Addison-Wesley заслуживает высокой оценки за осуществление редактирования и производственного процесса, а также за терпимость к причудам автора, касавшимся не только текста, но и внешнего дизайна книги, оформления и маркетинга.

 

Часть I Контекст

 

1

Философские вопросы

 

1.1. Культура? Какая культура?

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

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

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

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

 

1.2. Долговечность Unix

Операционная система Unix родилась в 1969 году и с момента возникновения находится в процессе постоянного использования и развития. Unix пережила несколько эпох, ограниченных стандартами компьютерной индустрии, — она старше, чем персональные компьютеры, рабочие станции, микропроцессоры или даже терминалы с видеодисплеями, и является современником первых полупроводниковых модулей памяти. Из всех современных систем разделения времени (timesharing systems) только о VM/CMS производства корпорации IBM можно утверждать, что она существует более продолжительный период, однако Unix-машины обеспечили в сотни тысяч раз больше служебных часов. Действительно, Unix, вероятно, поддерживает больший объем компьютерных вычислений, чем все остальные системы разделения времени.

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

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

Сомнительные предсказания о том, что Unix иссякнет или будет вытеснена другими операционными системами, постоянно высказываются с момента ее возникновения. Но до сих пор Unix, воплощенная сегодня в Linux, BSD Solaris и MacOS X и около десятка других вариантов, выглядит сильнее, чем когда-либо.

Роберт Меткалф (Robert Metcalf), создатель Ethernet, говорит, что если кто-либо разработает технологию, заменяющую Ethernet, то она будет названа "Ethernet", поэтому Ethernet не умрет никогда [2] . Unix уже пережила несколько подобных трансформаций.
Кен Томпсон.

Как минимум одна из центральных технологий Unix — язык С — широко распространен за пределами данной операционной системы. Действительно, в наши дни трудно представить разработку программного обеспечения без С, повсеместно используемого в качестве общего языка системного программирования. В Unix также были представлены широко распространенное в наши дни древовидное пространство имен файлов с узлами каталогов и конвейеры (pipeline) для сообщения программ.

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

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

Во многом стабильность и успех рассматриваемой операционной системы связаны с конструкторскими решениями Кена Томпсона, Денниса Ритчи, Брайана Кернигана, Дуга Макилроя, Роба Пайка и других разработчиков первых версий Unix. Однако стабильность и успех Unix также связаны с проектной философией, искусством программирования и технической культурой, которые развивались вокруг Unix.

 

1.3. Доводы против изучения культуры Unix

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

Непрофессионалы часто отвергают Unix, считая ее академической игрушкой или "песочницей для хакеров". Так, широко известный спор, Unix Hater's Handbook [27], длится почти столько же лет, сколько лет самой Unix, причем в ходе этого спора ее приверженцев слишком часто называли чудаками и неудачниками. Свою роль в этом, несомненно, сыграли колоссальные и повторяющиеся ошибки корпораций

AT&T, Sun, Novell, а также других коммерческих поставщиков и консорциумов по стандартизации в позиционировании и маркетинговой поддержке Unix.

Даже "изнутри" данная система не выглядит стабильной и универсальной. Скептики говорят, что Unix слишком полезна, чтобы умереть, но слишком неудобна, чтобы вырваться из лабораторий, т.е. считают ее только "нишевой" операционной системой.

Более всего доводы скептиков опровергает подъем операционной системы Linux и других Unix-систем с открытым исходным кодом (таких как современные варианты BSD). Культура Unix показала себя "слишком живучей", чтобы разрушиться даже после десятка ошибок поставщиков. В настоящее время Unix-сообщество, принявшее на себя управление технологией и маркетингом, быстро и очевидно решает проблемы данной операционной системы (способы разрешения проблем более подробно рассматриваются в главе 20).

 

1.4. Что в Unix делается неверно

Для конструкции, начало которой было положено в 1969 году, в высшей степени трудно идентифицировать конструкторские решения, которые определенно являются ошибочными.

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

Однако, возможно, что наиболее веские возражения против Unix являются следствием одного из аспектов ее философии, впервые в явном виде выдвинутого разработчиками системы X Window. Система X стремится обеспечить "механизм, а не политику" ("mechanism, not policy"), поддерживая чрезвычайно общий набор графических операций и передвигая возможность выбора инструментального набора, а также внешнего вида интерфейса (то есть политику), на уровень приложения. Подобные тенденции характерны и для других служб системного уровня в Unix. Окончательный выбор режима работы все в большей степени определяется пользователем, для которого доступно целое множество оболочек (shells). Unix-программы обычно обеспечивают несколько вариантов работы и активно используют сложные средства представления.

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

Эта доктрина была четко определена в Bell Labs Диком Хеммингом (Dick Hamming) 2 . В 50-х годах прошлого века, когда компьютеры были редкими и дорогими, он настаивал на том, что система общественных вычислительных центров (open-shop computing), где клиенты имеют возможность писать собственные программы, является крайне необходимой. Он считал, что: "лучше решить правильно выбранную проблему неверным путем, чем верным путем решить не ту проблему".
Дуг Макилрой.

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

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

 

1.5. Что в Unix делается верно

 

Недавний взрывной рост популярности операционной системы Linux и возрастающая важность Internet дают весомые причины полагать, что доводы скептиков неверны. Однако даже если скептическая оценка справедлива, Unix-культуру стоит изучать, поскольку существует ряд моментов, которые в Unix реализованы гораздо лучше, чем в конкурирующих операционных системах.

 

1.5.1. Программное обеспечение с открытым исходным кодом

Несмотря на то, что понятия "открытый исходный код" (open source) и "определение открытого исходного кода" (open source definition) были сформулированы в 1998 году, коллективная разработка свободно распространяемого исходного кода была ключевой особенностью культуры Unix с момента ее возникновения.

В течение первых десяти лет первоначальная версия Unix, разработанная корпорацией AT&T, и ее основной вариант Berkeley Unix обычно распространялись с исходным кодом, что способствовало возникновению большинства других полезных явлений, которые описываются ниже.

 

1.5.2. Кроссплатформенная переносимость и открытые стандарты

Unix остается единственной операционной системой, которая в гетерогенной среде компьютеров, поставщиков и специализированного аппаратного обеспечения способна представить связный и документированный программный интерфейс приложений (Application Programming Interface — API). Она является единственной операционной системой, которую можно масштабировать от встроенных микросхем и карманных компьютеров до настольных машин, серверов и всего спектра вычислительной техники, включая узкоспециальные вычислительные комплексы и серверы баз данных.

API-интерфейс Unix— ближайший элемент к независимому от аппаратного обеспечения стандарту для написания действительно совместимого программного обеспечения. Не случаен тот факт, что стандарт, первоначально названный институтом IEEE стандартом переносимых операционных систем (Portable Operating System Standard), вскоре приобрел соответствующий суффикс и стал называться POSIX. Unix-эквивалент API был единственной заслуживающей доверия моделью для такого стандарта.

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

 

1.5.3. Internet и World Wide Web

Контракт Министерства обороны США на первую реализацию набора протоколов TCP/IP был направлен группе разработчиков Unix, поскольку исходные коды данной операционной системы были в значительной степени открытыми. Кроме TCP/IP, Unix стала одной из необходимых центральных технологий индустрии ISP (Internet Service Provider — провайдер Internet-услуг). Со времени выхода из употребления семейства операционных систем TOPS в середине 80-х годов двадцатого века большинство Internet-серверов (а фактически все машины выше уровня персональных компьютеров) стали работать под управлением Unix.

Даже ошеломляющее маркетинговое влияние корпорации Microsoft не способно потеснить распространение операционной системы Unix в Internet. Хотя TCP/IP-стандарты (на которых основывается Internet) развивались в среде TOPS-IO и теоретически отделены от Unix, попытки заставить их работать в других операционных системах скованы несовместимостью, нестабильностью и ошибками. Теория и спецификации являются общедоступными, однако инженерные традиции, позволяющие преобразовать их в единую и работающую реальность, существуют только в мире Unix4 .

Слияние технической культуры Internet и Unix-культуры началось в начале 80-х годов прошлого века, и в настоящее время эти культуры нераздельно переплетены. Своей конструкцией технология World Wide Web, "современное лицо" Internet, настолько же обязана Unix, насколько и своей предшественнице — сети ARPANET. В частности, концепция универсального указателя ресурсов (Uniform Resource Locator— URL), центрального элемента Web является обобщением характерной для Unix идеи о едином пространстве именования файлов. Для того чтобы решать проблемы на уровне Internet-эксперта, понимание Unix и ее культуры является чрезвычайно важным.

 

1.5.4. Сообщество открытого исходного кода

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

В настоящее время это сообщество является мощной группой поддержки для всех видов разработки программного обеспечения. Мир Unix изобилует высококачественными средствами разработки с открытыми исходными кодами (многие из которых рассмотрены далее в настоящей книге). Unix-приложения с открытым исходным кодом обычно эквивалентны, а часто и превосходят свои частные аналоги [23]. Полные Unix-подобные операционные системы с совершенными инструмента-риями и пакетами основных приложений доступны для бесплатной загрузки через Internet. Зачем создавать программы с нуля, когда можно адаптировать, использовать повторно, перерабатывать и экономить 90% рабочего времени, используя общедоступный код?

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

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

 

1.5.5. Гибкость на всех уровнях

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

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

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

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

 

1.5.6. Особый интерес исследования Unix

Люди, провозглашающие техническое превосходство системы Unix, часто не уделяют достаточного внимания, может быть, наиболее важному ее преимуществу. Исследование Unix представляет особый интерес.

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

Следует отметить, что это можно сказать далеко не о многих системах. Действительно, напряжение и труд разработчика в других средах часто сравнивают с выталкиванием мертвого кита с мели5 . Напротив, в мире Unix операционная система скорее вознаграждает усилия, чем вызывает разочарование. Программисты в Unix обычно видят в ней не противника, победа над которым является главной целью, а скорее соратника.

В этом есть реальное экономическое значение. Фактор занимательности, конечно, сыграл свою роль. Людям нравилась Unix, поэтому они разрабатывали для нее больше программ, которые сделали ее использование приятным. В наши дни целые Unix-системы промышленного качества с открытым исходным кодом создаются людьми, которые воспринимают такую свою деятельность как хобби. Для того чтобы понять насколько это удивительно, достаточно попытаться найти людей, которые интереса ради занимаются клонированием операционных систем OS/360, VAX/VMS или Microsoft Windows.

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

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

 

1.5.7. Уроки Unix применимы в других операционных системах

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

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

 

1.6. Основы философии Unix

 

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

Философия Unix не является формальным методом проектирования. Она не была та свыше" как способ создания теоретически идеального программного обеспечения. Unix-философия (как удачные народные традиции в других инженерных дисци-инах) прагматична и основывается на опыте. Ее следует искать не в официальных ггодах и стандартах, а скорее в скрытых почти рефлекторных знаниях и опыте, который передается культурой Unix. Она культивирует чувство меры и достаточный септицизм.

Дуг Макилрой, изобретатель каналов (pipes) в Unix и один из основателей Unix-радиции, сформулировал постулаты философии Unix следующим образом [52].

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

• Будьте готовы к тому, что вывод каждой программы станет вводом другой, еще неизвестной программы. Не загромождайте вывод посторонней информацией. Избегайте строгих табличных или двоичных форматов ввода. Не настаивайте на интерактивном вводе.

• Проектируйте и создавайте программное обеспечение, даже операционные системы, которые можно будет проверить в самом начале, в идеальном случае в течение нескольких недель. Без колебаний выбрасывайте громоздкие части и перестраивайте их.

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

Позднее он обобщил эти положения (процитировано в книге "A Quarter Century of Unix" [74].

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

Роб Пайк, который стал одним из великих мастеров языка С, в книге "Notes on С Programming" [62] предлагает несколько иной угол зрения.

Правило 1. Невозможно сказать, где возникнет задержка в программе. "Бутылочные горлышки" возникают в неожиданных местах, поэтому не следует пытаться делать предсказания и исправлять скорость до тех пор, пока не будет точно выяснено, где находится "бутылочное горлышко".

Правило 2. Проводите измерения. Не следует регулировать скорость до тех пор, пока не проведены измерения, и даже после измерений, если одна часть кода подавляет остальные.

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

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

Правило 5. Данные доминируют. Если выбраны правильные структуры данных и все организовано хорошо, то алгоритмы почти всегда будут очевидными. Для программирования центральными являются структуры данных, а не алгоритмы6 .

Правило 6. Правила 6 нет.

Кен Томпсон, спроектировавший и реализовавший первую Unix, усилил четвертое правило Пайка афористичным принципом, достойным Дзэн-патриарха:

В случае сомнений используйте грубую силу.

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

1. Правило модульности: следует писать простые части, связанные ясными интерфейсами.

2. Правило ясности: ясность лучше, чем мастерство.

3. Правило композиции: следует разрабатывать программы, которые будут взаимодействовать с другими программами.

4. Правило разделения: следует отделять политику от механизма и интерфейсы от основных модулей.

5. Правило простоты: необходимо проектировать простые программы и "добавлять сложность" только там, где это необходимо.

6. Правило расчетливости: пишите большие программы, только если после демонстрации становится ясно, что ничего другого не остается.

7. Правило прозрачности: для того чтобы упростить проверку и отладку программы, ее конструкция должна быть обозримой.

8. Правило устойчивости: устойчивость— следствие прозрачности и простоты.

9. Правило представления: знания следует оставлять в данных, чтобы логика программы могла быть примитивной и устойчивой.

10. Правило наименьшей неожиданности: при проектировании интерфейсов всегда следует использовать наименее неожиданные элементы.

11. Правило тишины: если программа не может "сказать" что-либо неожиданное, то ей вообще не следует "говорить".

12. Правило исправности: когда программа завершается аварийно, это должно происходить явно и по возможности быстро.

13. Правило экономии: время программиста стоит дорого; поэтому экономия его времени более приоритетна по сравнению с экономией машинного времени.

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

15. Правило оптимизации: создайте опытные образцы, заставьте их работать, прежде чем перейти к оптимизации.

16. Правило разнообразия: не следует доверять утверждениям о "единственно верном пути".

17. Правило расширяемости: проектируйте с учетом изменений в будущем, поскольку будущее придет скорее, чем кажется.

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

 

1.6.1. Правило модульности: следует писать простые части, связанные ясными интерфейсами

Как однажды заметил Браян Керниган, "управление сложностью является сущностью компьютерного программирования" [41]. Отладка занимает большую часть времени разработки, и выпуск работающей системы обычно в меньшей степени является результатом талантливого проектирования, и в большей — результатом должного управления, исключающего многократное повторение ошибок.

Трансляторы, компиляторы, блок-схемы, процедурное программирование, структурное программирование, "искусственный интеллект", языки четвертого поколения, объектно-ориентированные языки и бесчисленные методологии разработки программного обеспечения рекламировались и продавались как средство борьбы с этой проблемой. Все они потерпели неудачу, если только их успех заключался в повышении обычного уровня сложности программы до той точки, где (вновь) человеческий мозг едва ли мог справиться. Как заметил Фред Брукс [8], "серебряной пули не существует".

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

 

1.6.2. Правило ясности: ясность лучше, чем мастерство

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

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

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

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

 

1.6.3. Правило композиции: следует разрабатывать программы, которые будут взаимодействовать с другими программами

Если разрабатываемые программы не способны взаимодействовать друг с другом, то очень трудно избежать создания сложных монолитных программ.

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

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

Текстовые потоки для Unix-инструментов являются тем же, чем являются сообщения для объектов в объектно-ориентированной среде. Простота интерфейса текстовых потоков усиливает инкапсуляцию инструментальных средств. Более сложные формы межпроцессного взаимодействия, такие как удаленный вызов процедур (remote procedure call), демонстрируют тенденцию к использованию программ с сильными внутренними зависимостями друг от друга.

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

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

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

Данная проблема подробнее обсуждается в главе 7.

 

1.6.4. Правило разделения: следует отделять политику от механизма и интерфейсы от основных модулей

В разделе "Что в Unix делается неверно" отмечалось, что разработчики системы X Window приняли основное решение о реализации "механизма, а не политики". Такой подход был направлен на то, чтобы сделать систему X общим сервером обработки графики и передать решение о стиле пользовательского интерфейса инстру-ментариям и другим уровням системы. Это оправданно, если учесть, что политика и механизм стремятся к изменению на протяжении различных периодов времени, причем политика меняется гораздо быстрее, чем механизм. Мода на вид и восприятие GUI-инструментариев может прийти и уйти, но растровые операции и компоновка останутся.

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

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

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

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

Другой способ заключается в разделении приложения на взаимодействующие процессы клиента (front-end) и сервера (back-end), которые обмениваются данными через специализированный протокол прикладного уровня посредством сокетов. Данный конструкторский подход рассматривается в главах 5 и 7. Во внешней или клиентской части реализуется политика, а во внутренней или серверной — механизм. Глобальная сложность данной пары часто является значительно меньшей, чем сложность одного процесса, в котором монолитно реализованы те же функции. Одновременно уменьшается уязвимость относительно ошибок и сокращаются затраты на жизненный цикл.

 

1.6.5. Правило простоты: необходимо проектировать простые программы и "добавлять сложность" только там, где это необходимо

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

Мнение о "замысловатой и красивой сложности" является почти оксюмороном. Unix-программисты соперничают друг с другом за "простоту и красоту". Эта мысль неявно присутствует в данных правилах, но ее стоит сделать очевидной.
Дуг Макилрой.

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

В любом случае, в конечном результате проигрывают все.

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

Таковой была бы культура, во многом похожая на культуру Unix.

 

1.6.6. Правило расчетливости: пишите большие программы, только если после демонстрации становится ясно, что ничего другого не остается

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

Проблема оптимального размера программного обеспечения более подробно рассмотрена в главе 13.

 

1.6.7. Правило прозрачности: для того чтобы упростить проверку и отладку программы, ее конструкция должна быть обозримой

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

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

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

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

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

 

1.6.8. Правило устойчивости: устойчивость-следствие прозрачности и простоты

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

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

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

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

Генри Спенсер.

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

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

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

 

1.6.9. Правило представления: знания следует оставлять в данных, чтобы логика программы могла быть примитивной и устойчивой

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

Данные более "податливы", чем программная логика. Это означает, что если можно выбирать между сложностью структуры данных и сложностью кода, следует выбирать первое. Более того, развивая проект, следует активно искать пути перераспределения сложности из кода в данные.

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

Данные методики также описываются в главе 9.

 

1.6.10. Правило наименьшей неожиданности: при проектировании интерфейсов всегда следует использовать наименее неожиданные элементы

Данное правило также широко известно под названием "Принцип наименьшего удивления" (Principle of Least Astonishment).

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

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

Необходимо учитывать характер предполагаемой аудитории. С программой могут работать конечные пользователи, другие программисты или системные администраторы.

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

Многие из этих традиций рассматриваются в главах 5 и 10.

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

 

1.6.11. Правило тишины: если программа не может "сказать" что-либо неожиданное, то ей вообще не следует "говорить"

Одно из старейших и наиболее постоянных правил проектирования в Unix гласит: если программа не может "сказать" что-либо интересное или необычное, то ей следует "молчать". Правильно организованные Unix-программы выполняют свою работу "ненавязчиво", с минимальным шумом и беспокойством. Молчание — золото.

Правило "молчание — золото" развивалось изначально, поскольку операционная система Unix предшествовала видеодисплеям. На медленных печатающих терминалах в 1969 году каждая строка излишнего вывода вызывала серьезные потери пользовательского времени. В наши дни данное ограничение снято, однако веские причины для краткости остаются.

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

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

Более подробно правило тишины и причины для его соблюдения описаны в конце главы 11.

 

1.6.12. Правило исправности: когда программа завершается аварийно, это должно происходить явно и по возможности быстро

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

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

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

В то же время следует учитывать следующее предостережение.

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

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

 

1.6.13. Правило экономии: время программиста стоит дорого; поэтому экономия его времени более приоритетна по сравнению с экономией машинного времени

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

Хотя почему-то практика, видимо, отстает от реальности. Если бы этот принцип принимался действительно серьезно в процессе разработки программного обеспечения, то большинство приложений были бы написаны на высокоуровневых языках типа Perl, Tel, Python, Java, Lisp и даже на языках командных интерпретаторов — т.е. на языках, сокращающих нагрузку на программиста, осуществляя собственное управление памятью ([65]).

И это действительно происходит в мире Unix, хотя за его пределами большинство разработчиков приложений, кажется, не в состоянии отойти от стратегии старой школы Unix, предполагающей кодирование на С (или С++). Данная стратегия и связанные с ней компромиссы подробнее описаны далее в настоящей книге.

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

 

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

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

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

В традициях Unix генераторы кода интенсивно используются для автоматизации чреватой ошибками кропотливой работы. Классическими примерами генераторов кода являются грамматические (parser) и лексические (lexer) анализаторы. Более новые примеры — генераторы шаке-файлов и построители GUI-интерфейсов.

Данные методики рассматриваются в главе 9.

 

1.6.15. Правило оптимизации: создайте опытные образцы, заставьте их работать, прежде чем перейти к оптимизации

Самый основной аргумент в пользу создания прототипов впервые был выдвинут Керниганом и Плоджером (Plauger): "90% актуальной и реальной функциональности лучше, чем 100% функциональности перспективной и сомнительной". Первоначальное создание прототипов помогает избежать слишком больших затрат времени для получения минимальной выгоды.

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

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

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

В мире Unix имеется общепринятая и весьма явная традиция (ярко проиллюстрированная приведенными выше комментариями Роба Пайка и принципом Кена Томпсона о грубой силе), которая гласит: создавайте прототипы, а затем шлифуйте их. Заставьте прототип работать, прежде чем оптимизировать его. Или: сначала заставьте прототип работать, а потом заставьте его работать быстро. Гуру "Экстремального программирования" Кент Бек (Kent Beck), работающий в другой культуре, значительно усилил данный принцип: "заставьте программу работать, заставьте ее работать верно, а затем сделайте ее быстрой".

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

Создание прототипов так же важно для конструкции системы, как и оптимизация — гораздо проще определить, выполняет ли прототип возложенные на него задачи, чем читать длинную спецификацию. Я помню одного менеджера разработки в Bellcore, который боролся против культуры "требований" задолго до того, как все заговорили о "быстром создании прототипов" (fast prototiping), или "гибкой разработке" (agile development). Он не стал бы выпускать длинные спецификации. Он связывал сценарии оболочки и awk-код в некоторую комбинацию, которая делала приблизительно то, что ему было нужно, а затем просил заказчиков направить к нему нескольких клерков на пару дней. После чего приглашал заказчиков прийти и посмотреть, как их клерки используют прототип, н сказать ему, нравится им это или нет. В случае положительного ответа он говорил, что "промышленный образец может быть создан через столько-то месяцев и по такой-то цене". Его оценки были довольно точными, однако он проигрывал в культуре менеджерам, которые верили, что создатели требований должны контролировать все.
Майк Леек.

Использование прототипов для определения того, в каких функциях нет необходимости, способствует оптимизации производительности; нет необходимости оптимизировать то, что не написано. Наиболее мощным средством оптимизации можно назвать клавишу "Delete".

В один из наиболее продуктивных дней я удалил тысячу строк кода.
Кен Томпсон.

Более глубоко соответствующие соображения рассматриваются в главе 12.

 

1.6.16. Правило разнообразия: не следует доверять утверждениям о "единственно верном пути"

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

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

 

1.6.17. Правило расширяемости: проектируйте с учетом изменений в будущем, поскольку будущее придет скорее, чем кажется

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

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

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

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

 

1.7. Философия Unix в одном уроке

Вся философия в действительности сводится к одному железному правилу ведущих инженеров, священному "принципу KISS":

Unix предоставляет великолепную основу для применения принципа KISS. В последующих главах данной книги описано, как его следует применять.

 

1.8. Применение философии Unix

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

• Все, что может быть фильтром, независимым от отправителя и получателя, должно быть таким фильтром.

• Потоки данных должны быть, если такое вообще возможно, текстовыми (для того чтобы их можно было просматривать и фильтровать с помощью стандартных средств).

• Структура баз данных и протоколы приложений должны быть, если это возможно, текстовыми (доступными человеку для чтения и редактирования).

• Сложные клиенты (пользовательские интерфейсы) должны быть четко отделены от сложных серверов.

• При возможности перед кодированием на С всегда нужно создавать прототип на каком-либо интерпретируемом языке.

• Смешивание языков лучше, чем написание всей программы на одном языке, тогда и только тогда, когда использование одного языка чрезмерно усложняет программу.

• Будьте "великодушны" к тому, что поступает, и строги к тому, что выпускается.

• При фильтровании не следует отбрасывать излишнюю информацию.

• Малое прекрасно. Следует писать программы, которые выполняют минимум, достаточный для решения задачи.

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

 

1.9. Подход также имеет значение

Когда верное решение очевидно, его следует немедленно использовать — данный подход может показаться работоспособным только в краткосрочной перспективе, однако это путь наименьших усилий в продолжительном периоде. Если не известно, какое решение является правильным, следует сделать минимум, необходимый для решения задачи, по крайней мере, до тех пор, пока не выяснится, что является правильным.

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

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

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

Для того чтобы правильно применять философию Unix, необходимо прийти (или вернуться) к описанному подходу. Необходимо интересоваться. Необходимо экспериментировать. Необходимо усердно исследовать.

Авторы надеются, что читатель при изучении оставшейся части книги воспользуется этим подходом, или, по крайней мере, что данная книга поможет открыть этот подход заново.

 

2 История: слияние двух культур

 

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

 

2.1. Истоки и история Unix, 1969—1995 гг.

 

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

Первоначальная Unix была третьей системой. Ее прародителем была небольшая и простая система CTSS (Compatible Time-Sharing System — совместимая система разделения времени), она была либо первой, либо второй из используемых систем разделения времени (в зависимости от некоторых вопросов определения, которые вполне можно не учитывать). Систему CTSS сменил революционный проект Multics, попытка создать "информационную утилиту" с группами функций, которая бы изящно поддерживала интерактивное разделение процессорного времени мэйнфреймов крупными сообществами пользователей. Увы, проект Multics рухнул "под собственным весом". Вместе с тем этот крах положил начало операционной системе Unix.

 

2.1.1. Начало: 1969-1971 гг.

Операционная система Unix возникла в 1969 году как детище разума Кена Томпсона, компьютерного ученого Bell Laboratories. Томпсон был исследователем в проекте Multics. Этот опыт утомлял Томпсона из-за примитивности пакетных вычислений, которые господствовали практически повсеместно. Однако в конце 60-х годов идея разделения времени все еще была новой. Первые предположения, связанные с ней, были выдвинуты почти десятью годами ранее компьютерным ученым Джоном Маккарти (John McCarthy) (который также известен как создатель языка Lisp), а первая фактическая реализация состоялась в 1962 году, семью годами ранее, и многопользовательские операционные системы все еще оставались экспериментальными и непредсказуемыми.

Аппаратное обеспечение компьютеров в то время было еще более примитивным. Наиболее мощные машины в те дни имели меньшую вычислительную мощность и внутреннюю память, чем обычный современный сотовый телефон8 . Терминалы с видеодисплеями находились в начальной стадии своего развития и в течение последующих шести лет не получили широкого распространения. Стандартным интерактивным устройством на ранних системах разделения времени был телетайп ASR-33 — медленное, шумное устройство, которое печатало только символы верхнего регистра на больших рулонах желтой бумаги. ASR-33 послужит прародителем Unix-традиции в плане использования кратких команд и немногословных откликов.

Когда Bell Labs вышла из состава исследовательского консорциума Multics, у Кена Томпсона остались некоторые идеи создания файловой системы, вдохновленные проектом Multics. Кроме того, он остался без машины, на которой мог бы играть в написанную им игру "Space Travel" (Космическое путешествие), научно-фантастический симулятор управления ракетами в солнечной системе. Unix начала свой жизненный путь на восстановленном мини-компьютере PDP-79 в качестве платформы для игры Space Travel и испытательного стенда для идей Томпсона о разработке операционной системы. Подобный компьютер показан на рис. 2.1.

Полная история происхождения описана в статье [69] с точки зрения первого помощника Томпсона, Денниса Ритчи, который впоследствии стал известен как соавтор Unix и создатель языка С. Деннис Ритчи, Дуг Макилрой и несколько их коллег привыкли к интерактивным вычислениям в системе Multics и не хотели терять эту возможность.

Ритчи отмечает: "То, что мы хотели сохранить, было не только хорошей средой для программирования, но и системой, вокруг которой могло сформироваться братство. Мы знали по опыту, что сущностью совместных вычислений, которые обеспечивались с помощью удаленного доступа к машинам с разделением времени, является не только ввод программ с клавиатуры в терминал вместо использования клавишного перфоратора, но и поддержка тесного общения". В воздухе витала идея рассматривать компьютеры не просто как логические устройства, а как ядра сообществ. 1969 год был также годом изобретения сети ARPANET (прямого предка современной сети Internet). Тема "братства" будет звучать во всей последующей истории Unix.

Реализация игры Томпсона и Ритчи "Space Travel" привлекла к себе внимание. Вначале программное обеспечение PDP-7 приходилось перекомпилировать на GE-мэйнфрейме. Программные утилиты, которые были написаны Томпсоном и Ритчи на самом PDP-7, чтобы поддерживать развитие игры, стали каркасом Unix, хотя само название не было закреплено за системой до 1970 года. Исходный вариант написания представлял собой аббревиатуру "UNICS" (UNiplexed Information and Computing Service). Позднее Ритчи описывал эту аббревиатуру как "слегка изменнический каламбур на слово "Multics", которое означало MULTiplexed Information and Computing Service.

Даже на самых ранних стадиях развития PDP-7 Unix была весьма похожа на современные Unix-системы и предоставляла гораздо более приятную среду программирования, чем доступные в то время мэйнфреймы с использованием перфокарт. Unix была весьма близкой к первой системе, используя которую программист мог находиться непосредственно перед машиной и создавать программы на лету, исследуя возможности и тестируя программы в процессе их создания. На протяжении всей жизни Unix реализуется модель развития возможностей путем привлечения высокоинтеллектуальных, добровольных усилий со стороны программистов, которых раздражают ограничения других операционных систем. Эта модель возникла на раннем этапе внутри самой корпорации Bell Labs.

Рис. 2.1. Мини-компьютер PDP-7

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

Первой реальной задачей Unix в 1971 году была поддержка того, что в наши дни назвали бы текстовым процессором, для патентного департамента Bell Labs. Первым Unix-приложением был предшественник программы для форматирования текста nroff(1). Этот проект оправдал приобретение гораздо более мощного мини-компьютера PDP-11. Руководство оставалось в счастливом неведении о том, что система обработки текста, которую создавали Томпсон и его коллеги, была инкубатором для операционной системы. Операционные системы не входили в планы Bell Labs — AT&T присоединилась к консорциуму Multics именно для того, чтобы избежать разработки собственной операционной системы. Тем не менее, завершенная система имела воодушевляющий успех, который утвердил Unix в качестве постоянной и ценной части системы вычислений в Bell Labs и привел к появлению другой темы в истории Unix — тесной связи со средствами набора и форматирования документов, а также средствами коммуникации. Справочник 1972 года говорил о 10 инсталляциях.

Позднее Дуг Макилрой напишет об этом периоде [53]: "Давление коллег и простая гордость своей квалификацией приводили к переписыванию или удалению больших фрагментов кода, по мере того, как появлялись лучшие или более фундаментальные идеи. Профессиональная конкуренция и защита сфер влияния были практически не известны: возникало так много хороших идей, что никому не требовалось быть собственником инноваций". Однако понадобится четверть века для того, чтобы сообществу стали ясны все выводы из этого наблюдения.

 

2.1.2. Исход: 1971-1980 гг.

Первоначально операционная система Unix была написана на ассемблере, а ее приложения — на "смеси" ассемблера и интерпретируемого языка, который назывался "В". Его преимущество заключалось в том, что он был достаточно мал для работы на компьютерах PDP-7. Однако язык В не был достаточно мощным для системного программирования, поэтому Деннис Ритчи добавил в него типы данных и структуры, в результате чего появился язык С. Это произошло в начале 1971 года. А в 1973 году Томпсон и Ритчи наконец успешно переписали Unix на новом языке. Это был весьма смелый шаг. В то время для того чтобы получить максимальную производительность аппаратного обеспечения, системное программирование осуществлялось на ассемблере, и сама концепция переносимой операционной системы представлялась еще весьма сомнительной. Только в 1979 году Ритчи смог написать: "Кажется бесспорным, что в основном успех Unix обусловлен читаемостью, редак-тируемостью и переносимостью ее программного обеспечения, причем такие позитивные характеристики, в свою очередь, являются следствием ее написания на языках высокого уровня".

В 1974 году журнал Communications of the ACM [72] впервые представил Unix широкой общественности. В статье авторы описывали беспрецедентно простую конструкцию Unix и сообщали о более чем 600 инсталляций данной операционной системы. Все инсталляции производились на машинах, мощность которых была низкой даже по стандартам того времени, однако (как писали Ритчи и Томпсон) "ограничения способствовали не только экономии, но также и определенному изяществу дизайна".

После доклада в САСМ исследовательские лаборатории и университеты по всему миру заявили о желании испытать Unix самостоятельно. По соглашению сторон об урегулировании антитрастового дела 1958 года корпорации AT&T (родительской организации Bell Labs) запрещалось входить в компьютерный бизнес. Таким образом, Unix невозможно было превратить в продукт. Действительно, в соответствии с положениями соглашения, Bell Labs должна была лицензировать свою нетелефонную технологию всем желающим. Кен Томпсон без огласки начал отвечать на запросы, отправляя ленты и дисковые пакеты, каждый из которых, согласно легенде, подписывался "с любовью, Кен" (love, ken).

Напомним, что эти события происходили задолго до появления персональных компьютеров. Аппаратное обеспечение, необходимое для работы Unix, было слишком дорогостоящим, для того, чтобы использоваться в индивидуальных исследованиях. Поэтому Unix-машины были доступны, только благодаря благоволению больших организаций с большим бюджетом: корпораций, университетов, правительственных учреждений. Но использование таких мини-компьютеров было менее контролируемым, чем использование больших мэйнфреймов, и Unix-разработка быстро "приобрела дух контркультуры". Это было начало 70-х годов прошлого века. Первопроходцами Unix-программирования были лохматые хиппи и те, кто хотел на них походить. Они наслаждались, исследуя операционную систему, которая не только предлагала им интересные испытания на переднем крае компьютерной науки, но также и подрывала все технические предположения и бизнес-практику, которая сопутствовала "большим вычислениям". Перфокарты, язык COBOL, деловые костюмы и пакетные мэйнфреймы IBM остались в "презренном прошлом". Unix-хакеры упивались тем, что одновременно строили будущее и играли с системой.

Энтузиазм тех дней описывается цитатой Дугласа Комера (Douglas Comer): "Многие университеты вносили свой вклад в Unix. В Университете Торонто кафедра приобрела принтер/плоттер с разрешением 200 точек на дюйм и создала программное обеспечение, которое использовало его для имитации фотонаборного аппарата. В Йельском университете (Yale University) студенты и компьютерные ученые модифицировали командный интерпретатор Unix. В Университете Пурдью (Purdue University) кафедра электротехники добилась значительного улучшения производительности, выпустив версию Unix, которая поддерживала большее количество пользователей. В Пурдью также разработали одну из первых компьютерных сетей на основе Unix. Студенты Калифорнийского университета в Беркли разработали новый командный интерпретатор и десятки небольших утилит. К концу 70-х годов, когда Bell Labs выпустила Version 7 UNIX, было ясно, что система решала вычислительные задачи многих факультетов и что она воплотила в себе множество появившихся в университетах идей. Конечным результатом стало появление укрепленной системы. Прилив идей послужил началом нового цикла интеллектуального взаимообмена академического мира и производственных лабораторий и в конечном итоге обусловил рост коммерческих вариантов Unix" [13J.

Первой узнаваемой версией Unix была версия 7 (Version 7), выпущенная в 1979 году10 . Первая группа пользователей Unix сформировалась за год до этого. К тому времени Unix использовалась для операционной поддержки всех систем Bell System [35], и получила распространение в университетах вплоть до Австралии, где заметки Джона Лайонза (John Lions) [49] в 1976 году по исходному коду Version 6 стали первой серьезной документацией по внутреннему устройству ядра Unix. Многие пожилые Unix-хакеры до сих пор свято хранят копии этих заметок.

Рис. 2.2. Кен Томпсон (сидя) и Деннис Ритчи перед PDP-11 в 1972 году

Книга Лайонза была самиздатовской сенсацией. Из-за несоблюдения авторских прав или чего-то еще ее нельзя было публиковать в США, поэтому везде "просачивались" копии копий. Я до сих пор храню свою, которая была копией как минимум шестого поколения. Не имея книги Лайонза, тогда невозможно было быть хакером ядра.
Кен Арнольд.

Первые годы Unix-индустрии также были временем объединения. Первая Unix-компания (Santa Cruz Operation, SCO) начала свою работу в 1978 году, и в том же году продала первый коммерческий компилятор С (Whitesmiths). К 1980 году малоизвестная компания, производитель программного обеспечения в Сиэтле, также вступила в Unix-игру, распространяя вариант АТ&Т-версии Unix для мини-компьютеров, который назывался XENIX. Но привязанность Microsoft к Unix как к продукту не была долгой (хотя Unix использовалась для большей части внутренней разработки компании вплоть до начала 1990-х годов).

 

2.1.3. TCP/IP и Unix-войны: 1980-1990 гг.

Студенческий городок Калифорнийского университета в Беркли вначале был единственным важнейшим академическим центром Unix-разработки. Unix-исследо-вания начались здесь в 1974 году и получили мощный толчок, когда Кен Томпсон преподавал в университете в течение академического отпуска 1975-1976 годов. Первая BSD-версия была создана на базе лабораторной разработки в 1977 году неизвестным до этого аспирантом Биллом Джоем (Bill Joy). К 1980 году Беркли стал центром сети университетов, активно дополняющих свой вариант Unix. Идеи и код из Berkeley Unix (включая редактор vi(1)) были переданы из Беркли обратно в Bell Labs.

Затем в 1980 году Агентству передовых исследований Министерства обороны США (Defense Advanced Research Projects Agency — DARPA) потребовалась команда для реализации новейшего набора протоколов TCP/IP на компьютерах VAX под Unix. Компьютеры PDP-10, поддерживающие сеть ARPANET, в то время устарели, и в воздухе уже витали идеи о том, что DEC может быть вынуждена отказаться от PDP-10 для поддержки VAX. Агентство DARPA рассматривало принятие DEC для реализации TCP/IP, однако отказалась от этой идеи, поскольку вызывал беспокойство тот факт, что DEC может не согласиться на изменения в собственной операционной системе VAX/VMS [48]. Вместо этого агентство DARPA в качестве платформы выбрало Berkeley Unix, явно ввиду того, что ее исходный код был доступным и свободным [45].

Исследовательская группа компьютерных наук (Computer Science Research Group) в Беркли оказалась в нужное время в нужном месте с надежнейшими инструментами разработки. Это была, несомненно, наиболее важная поворотная точка в истории Unix с момента ее появления.

До того как реализация протокола TCP/IP была выпущена с версией BSD 4.2 в 1983 году, Unix имела только слабую поддержку сети. Ранние эксперименты с Ethernet были неудовлетворительными. Для распространения программного обеспечения через обычные телефонные линии посредством модема в Bell Labs было разработано неприглядное, но вполне функциональное средство, которое называлось UUCP (Unix to Unix Copy Program — программа копирования из Unix в Unix)11 . С помощью UUCP можно было передавать Unix-почту между удаленными машинами. Кроме того, (после того, как в 1981 году была изобретена Usenet) UUCP поддерживала распределенные доски объявлений, которые позволяли пользователям широковещательно распространять текстовые сообщения везде, где были телефонные линии и Unix-системы.

Тем не менее, несколько Unix-пользователей, знакомых с яркими преимуществами ARPANET, испытывали существенные заруднения из-за отсутствия FTP и Telnet и очень ограниченного удаленного выполнения заданий и чрезвычайно медленных каналов. Ранее, до появления протоколов TCP/IP, Internet- и Unix-культуры не смешивались. Особое видение Деннисом Ритчи вопроса о компьютере как о способе "поддержки тесного общения" сформировало одно из университетских сообществ. Оно не расширилось до распределенной по всему континенту "сетевой нации", которую пользователи сети ARPA начали формировать в середине 70-х годов прошлого века. Первые пользователи ARPANET считали Unix грубой подделкой, "ковыляющей на смехотворно слабом аппаратном обеспечении".

После появления TCP/IP все изменилось. Началось слияние культур ARPANET и Unix. Это инициировало развитие, которое в конце концов спасло их от разрушения. Однако возникли новые проблемы, которые были результатом двух отдельных "бедствий": подъема Microsoft и падения AT&T.

В 1981 году корпорация Microsoft заключила свою историческую сделку с IBM по IBM PC. Билл Гейтс (Bill Gates) приобрел QDOS (Quick and Dirty Operating System), клон CP/M, собранный за шесть недель программистом Тимом Патерсоном (Tim Paterson), в Seattle Computer Products, где работал Тим Патерсон. Гейтс, скрывая от Патерсона и SCP сделку с IBM, приобрел права на систему за 50 тыс. долл. Затем он уговорил IBM разрешить Microsoft распространять на рынке операционную систему MS-DOS отдельно от аппаратного обеспечения PC. В течение следующего десятилетия выигрышный код, которого он не писал, сделал Билла Гейтса мультимиллиардером, а бизнес-тактика, еще более искусная, чем первоначальная сделка, принесли Microsoft монопольное положение на рынке настольных компьютеров. Операционная система XENIX как продукт была вскоре заброшена и в конце концов продана компании SCO.

В то время еще не было очевидно, насколько успешные (или деструктивные) действия собиралась предпринять Microsoft. Поскольку IBM PC-1 не обладала аппаратными возможностями поддержки Unix, пользователи Unix едва ли заметили эту платформу вообще (ирония в том, что операционная система DOS 2.0 затмила СР/М в основном из-за того, что один из основателей Microsoft Пол Аллен (Paul Allen) встроил в нее Unix-функции, включая подкаталоги и каналы). Рассмотрим события, которые кажутся более интересными, такие как возникновение в 1982 году компании Sun Microsystems.

Основатели Sun Microsystems, Билл Джой (Bill Joy), Андреас Бектолшейм (Andreas Bechtolsheim) и Винод Хосла (Vinod Khosla), начали создавать Unix-машину мечты со встроенной поддержкой сети. Они скомбинировали аппаратное обеспечение, спроектированное в Стэнфорде, с операционной системой Unix, разработанной в Беркли, и впоследствии основали индустрию рабочих станций. В то время никто не собирался контролировать доступ к исходному коду одной ветви дерева Unix, которая постепенно "высохла" в то время как Sun Microsystems начала вести себя все меньше как свободный проект и все больше как традиционная фирма. Университет в Беркли продолжал распространять BSD Unix вместе с исходным кодом. Официально лицензия на исходный код System III стоила 40 тыс. долл., однако Bell Labs закрывала глаза на рост количества распространяемых нелегальных лент с Bell Labs Unix, а университеты продолжали обмениваться кодом с Bell Labs. Складывалось впечатление, что коммерциализация Unix со стороны Sun — это лучшее, что могло произойти.

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

Когда в 1983 году DEC прекратила разработки по машине, которая являлась потомком PDP-10 (Jupiter), VAX-машины с использованием Unix стали занимать положение доминирующих Internet-машин, это положение они будут занимать до вытеснения их рабочими станциями Sun Microsystems. К 1985 году около 25% всех VAX-машин будут использовать Unix, причем несмотря на жесткое противостояние DEC. Однако самый долгосрочный эффект прекращения работ над проектом Jupiter был менее очевидным. Смерть хакерской культуры, развивавшейся вокруг компьютеров PDP-10 разработки MIT AI Lab, побудила программиста Ричарда Столлмена (Richard Stallman) к началу создания проекта GNU, полностью свободного клона Unix.

К 1983 году было не менее 6 Unix-подобных операционных систем для IBM-PC: uNETix, Venix, Coherent, Q.NX, Idris и вариант, поддерживаемый на низкоуровневой плате Sritek PC. Все еще не было вариантов ни версии System V, ни BSD-версии. Обе группы считали микропроцессор серии 8086 чрезвычайно маломощным и не планировали работать с ним. Ни одна из Unix-подобных операционных систем не добилась значительного коммерческого успеха, однако они показали значительную потребность в Unix на дешевом аппаратном обеспечении, которое ведущие производители оборудования не поставляли. Ни один человек не мог позволить себе приобрести лицензию на исходный код Unix.

Sun уже добилась успеха (с подражателями), когда в 1983 году Министерство юстиции США выиграло второй антитрастовый процесс против AT&T и раздробило корпорацию Bell System. Это освободило AT&T от соглашения 1958 года, препятствующего превращению Unix в продукт, и AT&T немедленно приступила к коммерциализации Unix System V. Этот шаг почти уничтожил Unix.

Это верно, но их маркетинг действительно распространил Unix по всему миру
Кен Томпсон.

Большинство сторонников Unix полагали, что разделение AT&T было хорошей новостью. Нам казалось, что новые условия дадут шанс здоровой Unix-индустрии — индустрии, использующей недорогие рабочие станции на основе процессоров 68000, что в конечном итоге разрушит монополию IBM.

Никто из нас в то время не осознавал, что превращение Unix в коммерческий продукт разрушит свободный обмен исходным кодом, который дал столько жизненной силы развивающейся системе. Не зная другой модели, кроме секретности для накопления прибыли от программного обеспечения и кроме централизованного управления разработкой коммерческого продукта, AT&T прекратила распространение исходного кода. Нелегальные ленты с Unix стали намного менее интересными, так как их использование могло повлечь за собой угрозу судебного преследования. Интеллектуальный вклад от университетов начал иссякать.

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

Другая менее очевидная ошибка заключалась в том, что все заинтересованные стороны вели себя так, будто персональные компьютеры и Microsoft не имеют отношения к перспективам Unix. В Sun Microsystems не разглядели того, что ставшие широко распространенными персональные компьютеры неизбежно начнут атаковать рынок рабочих станций Sun снизу. Корпорация AT&T, зациклившаяся на мини-компьютерах и мэйнфреймах, испытала несколько других стратегий, которые были направлены на то, чтобы стать главным игроком на рынке компьютеров, и крайне усугубила ситуацию. Для поддержки операционной системы Unix на PC-станциях были сформированы около десятка небольших компаний. Все они испытывали недостаток средств и уделяли основное внимание предоставлению своих услуг разработчикам и инженерам, т.е. никогда не ставили себе целью выход на рынок обслуживания предприятий и домашних пользователей, на который была нацелена Microsoft.

Действительно, в течение многих лет после падения AT&T Unix-сообщество было озабочено первой фазой Unix-войн — внутренними разногласиями и соперничеством между System V Unix и BSD Unix. Разногласия охватывали несколько уровней, ряд технических (сокеты против потоков, специальный терминальный интерфейс (tty) в BSD против общего терминального интерфейса (termio) в System V) и культурных вопросов. "Водораздел" пролегал приблизительно между хиппи и белыми воротничками. Программисты и технические специалисты склонялись к точке зрения Университета в Беркли и BSD Unix, а более ориентированные на бизнес специалисты — к точке зрения AT&T и System V Unix. Хиппи-программистам нравилось считать себя восставшими против корпоративной империи.

Однако в год разделения AT&T случилось нечто, что впоследствии приобрело более долгосрочную важность для Unix. Программист и лингвист по имени Ларри Уолл (Larry Wall) создал утилиту patch(1). Программа patch — простой инструмент, который применяет к базовому файлу изменения, сгенерированные утилитой diff(1). Она предоставила Unix-разработчикам возможность сотрудничать, передавая друг другу вместо полных файлов наборы "заплат", т.е. инкрементальные изменения кода. Это было важно не только потому, что заплаты были менее громоздкими, чем полные файлы, но и потому, что они часто применяются аккуратно, даже если большая часть базового файла претерпела изменения с тех пор, как отправитель заплаты получил свою копию. С помощью данного средства потоки разработки по общему базовому исходному коду могли разделяться, двигаться параллельно и сходиться снова. Программа patch сделала гораздо больше, чем любой другой инструмент, для активизации совместной разработки через Internet, т.е. активизации метода, который после 1990 года вдохнул в Unix новую жизнь.

В 1985 году корпорация Intel распространила первую микросхему 386-й серии, способную адресовать 4 Гбайт памяти с линейным адресным пространством. Неуклюжая сегментная адресация в процессорах 8086 и 286 очень быстро устарела. Это была важная новость, поскольку она означала, что впервые микропроцессор доминирующего семейства Intel стал способен работать под управлением Unix без болезненных компромиссов. Появление данного процессора предрекало грядущую катастрофу для Sun и других создателей рабочих станций, но они этого не заметили.

В том же году Ричард Столлмен опубликовал манифест GNU [78] и основал Фонд свободного программного обеспечения (Free Software Foundation). Очень немногие всерьез восприняли мнение Столлмена и его проект GNU, но он оказался прав. В независимой разработке того же года создатели системы X Window выпустили ее в виде исходного кода без указания права собственности, ограничений или лицензии. Как непосредственный результат этого решения возникла безопасно нейтральная зона для сотрудничества между Unix-поставщиками и потерпевшими поражение частными конкурентами с целью создания графической подсистемы Unix.

Кроме того, в 1983 году начались серьезные попытки по стандартизации согласования API-интерфейсов System V и Berkeley Unix вместе со стандартом /usr/group. За ним в 1985 году последовали стандарты POSIX, поддерживаемые институтом IEEE. В данных стандартах описывался пересекающийся набор вызовов BSD и SVR3 (System V Release 3), а также превосходная обработка сигналов Berkeley Unix и управление задачами, но с помощью терминального управления SVR3. Все последующие стандарты Unix будут базироваться на стандарте POSIX, а поздние Unix-системы будут строго его придерживаться. Единственным появившимся впоследствии главным дополнением к современному API-интерфейсу ядра Unix были BSD-сокеты.

В 1986 году Ларри Уолл, ранее разработавший утилиту patch(1), начал работу по созданию языка Perl, который станет первым и наиболее широко используемым языком написания сценариев с открытым исходным кодом. В начале 1987 года появилась первая версия GNU С-компилятора, а к концу того же года была определена основа инструментального набора GNU: редактор, компилятор, отладчик и другие базовые инструменты разработки. Тем временем система X Window начала появляться на относительно недорогих рабочих станциях. Эти компоненты в 90-хгодах прошлого века послужили каркасом для Unix-разработок с открытым исходным кодом.

Также в 1986 году PC-технология освободилась от власти компании IBM, которая продолжала сохранять соотношение "цена-мощность" во всей линейке своих продуктов, что благоприятствовало ее высокодоходному бизнесу по поставке мэйнфреймов. IBM отказалась от процессора 386 в большей части своей новой линейки компьютеров PS/2 в пользу более слабого процессора 286-й серии. Серия PS/2, которую IBM разработала на основе частной архитектуры системной шины, для того чтобы оградить себя от создателей клонов, стала колоссально дорогим провалом12 . Компания Compaq, самый активный создатель PC-клонов, превзошла IBM, выпустив первую машину с процессором 386. Даже при частоте процессора всего в 16 МГц, процессор 386-й серии сделал машину пригодной к использованию в среде Unix. Это был первый компьютер, который можно было назвать PC.

Проект Столлмена подтвердил возможность использовать машины 386-й серии для создания рабочих станций Unix по цене, почти на порядок меньшей, чем ранее. Как ни странно, видимо, никто в действительности не подумал об этом. Большинство Unix-программистов, "пришедших из мира мини-компьютеров и рабочих станций", продолжали пренебрегать дешевыми машинами 80x86, отдавая предпочтение более элегантным конструкциям на основе процессоров 68000. И хотя многие программисты способствовали успеху проекта GNU, большинство специалистов не видели его практических последствий в обозримом будущем.

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

В 1988 году Кен Олсен (Ken Olsen), президент корпорации DEC, "провозгласил" Unix чуть ли не панацеей. DEC поставляла собственный вариант Unix на компьютерах PDP-11 с 1982 года, однако в действительности рассчитывала перевести бизнес на частную операционную систему VMS. Корпорация DEC и индустрия мини-компьютеров столкнулись с крупными проблемами, их захлестнула волна мощных дешевых машин, продаваемых Sun Microsystems и остальными поставщиками рабочих станций. На большинстве этих рабочих станций использовалась Unix.

Однако собственные проблемы Unix-индустрии становились еще труднее. В 1988 году AT&T приобрела 20% акций Sun Microsystems. Две эти компании, лидеры Unix-рынка, начинали восставать против угрозы, созданной PC-станциями, корпорациями IBM и Microsoft, и осознавать, что предыдущие 5 лет "кровопролития" ослабили их. Альянс AT&T/Sun и разработка технических стандартов вокруг POSIX положили конец разногласиям между направлениями System V и BSD Unix. Однако началась "вторая фаза войн", когда поставщики второго уровня (IBM, DEC, Hewlett-Packard и другие) учредили Фонд открытого программного обеспечения (Open Software Foundation) и "выстроились против" линии AT&T/Sun (представленной международным сообществом Unix). Последовали новые этапы противостояния Unix против Unix.

Тем временем Microsoft зарабатывала миллиарды на рынке компьютеров для дома и малого бизнеса, на что воюющие стороны не пожелали обратить внимание. Выпуск в 1990 году Windows 3.0 — первой успешной операционной системы с графическим интерфейсом из Рэдмонда — закрепил доминирующее положение Microsoft и создал условия, которые позволили корпорации выровнять цены и монополизировать рынок настольных приложений 90-х годов.

Годы с 1989 по 1993 были самыми мрачными в истории Unix. Выяснилось, что мечты всего Unix-сообщества провалились. Междоусобная вражда чрезвычайно ослабила Unix-индустрию, почти лишила ее возможности противостоять Microsoft. Элегантные процессоры компании Motorola, которые предпочитали Unix-программисты, проиграли неказистым, но недорогим процессорам Intel. Проект GNU оказался неспособен выпустить свободное ядро Unix, что было обещано еще в 1985 году, и после нескольких лет отговорок доверие к нему стало падать. PC-технология была безжалостно превращена в коммерческий продукт. Пионеры хакерского движения 70-х годов достигли среднего возраста и сбавили темп. Аппаратное обеспечение дешевело, но Unix оставалась и дальше чрезмерно дорогой системой. Приверженцы Unix с опозданием поняли, что прежняя монополия IBM сменилась новой монополией Microsoft, а плохо сконструированное программное обеспечение Microsoft все больше заполняло рынок.

 

2.1.4. Бои против империи: 1991—1995 гг.

В 1990 году первую попытку противостояния сделал Вильям Джолитц (William Jolitz), опубликовав серию журнальных статей о перенесении BSD Unix на машины с процессором 386-й серии. Такой перенос был вполне возможным, так как, частично под влиянием Столлмена, хакер из университета в Беркли, Кит Бостик (Keith Bostic), в 1988 году начал удалять частный код AT&T из исходных файлов BSD. Однако проект 386BSD получил сильный удар, когда в конце 1991 года Джойлитц покинул проект и погубил собственную работу. Существует ряд противоречивых объяснений этому факту, однако все они имеют общую линию: Джойлитц хотел выпустить свой код как свободный, и был огорчен тем, что корпоративные спонсоры проекта выбрали более частную модель лицензирования.

В августе 1991 года Линус Торвальдс (Linus Torvalds), тогда еще неизвестный студент из Финляндии, объявил о проекте операционной системы Linux. Торвальдс вспоминает, что одним из главных мотивирующих факторов для него послужила высокая цена операционной системы Unix производства Sun Microsystems в его университете. Торвальдс также отмечал, что если бы он знал о проекте BSD Unix, то скорее присоединился бы к нему, чем создавал бы собственный проект. Однако проект 386BSD не распространялся до начала 1992 года, т.е. несколько месяцев спустя после появления первой версии Linux.

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

Потребовалось еще 2 года и взрывной рост Internet в 1993-1994 годах, прежде чем истинная важность Linux и дистрибутивов BSD с открытым исходным кодом стала очевидной для остальной части мира Unix. К несчастью для приверженцев BSD, судебное преследование BSDI (начинающей компании, которая поддерживала проект Джойлитца) поглощало большую часть времени и побудило нескольких ключевых разработчиков Berkeley Unix переключиться на Linux.

В то время немало было сказано о копировании кода и краже фирменных секретов. Контрафактный код не был идентифицирован в течение приблизительно 2 лет. Судебный процесс мог бы продлиться еще дольше, если бы корпорация Novell не приобрела USL у AT&T и не урегулировала спор. В конце концов, из 18 ООО файлов, составляющих дистрибутив, было удалено 3, а в другие файлы были внесены незначительные изменения. В дополнение к этому, университет согласился добавить указание на авторские права USL в почти 70 файлов при условии, что данные файлы и далее будут распространяться свободно.
Маршал Кирк Маккыозик.

Достигнутое соглашение создало важный прецедент, освободив полностью работающую Unix от частного контроля, однако его результаты для самой BSD Unix были крайне неприятными. Проблем не убавилось, когда в 1992-1994 годах Исследовательская группа компьютерных наук (Computer Science Research Group) в Беркли прекратила свою работу. Впоследствии междоусобное противостояние внутри BSD-сообщества разделилось на 3 конкурирующих проекта. В результате BSD-ветвь в решающее время осталась позади Linux и уступила данной операционной системе лидирующие позиции в Unix-сообществе.

Усилия разработчиков операционных систем Linux и BSD были естественными для Internet, чего нельзя сказать о предыдущих Unix-системах. Они опирались на распределенную разработку и инструмент Ларри Уолла (patch(1)), а также привлекали разработчиков посредством электронной почты и групп новостей Usenet. Соответственно, они получили огромный подъем, когда в 1993 году благодаря изменениям в телекоммуникационной технологии и приватизации магистральных Internet-каналов начали распространяться компании-провайдеры Internet-услуг. Этот процесс выходит за рамки описываемой истории. Потребность в дешевом Internet-доступе была вызвана другим фактором: изобретением в 1991 году технологии World Wide Web, которая была в Internet "приложением-приманкой" (killer арр), технологией графического пользовательского интерфейса, которая сделала его дружественным для огромного числа нетехнических конечных пользователей.

Массовый маркетинг Internet одновременно увеличил число потенциальных разработчиков и сократил стоимость транзакций при распределенной разработке. Результаты проявились в проектах наподобие XFree86, в котором использовалась Internet-центрированная модель для создания более эффективной организации разработчиков, чем официальный Консорциум X (X Consortium). Первый выпуск сервера XFree86 в 1992 году обеспечил Linux и BSD подсистемой графического пользовательского интерфейса, которой им не доставало. В течение последующего десятилетия XFree86 будет лидировать среди Х-разработок и основная деятельность Консорциума X будет состоять в отборе новаторских разработок, созданных в ХРгее86-сообществе, и направлении их обратно промышленным спонсорам консорциума.

К концу 1993 года операционная система Linux обладала как Internet-возможностями, так и системой X. Полный инструментарий GNU, обеспечивающий высококачественные средства разработки, поддерживался в Linux с самого начала. Более того, Linux была подобна чаше изобилия, притягивающей, накапливающей и концентрирующей 20 лет разработки программного обеспечения с открытым исходным кодом, которое до этого было рассеяно среди десятка различных частных Unix-платформ. Несмотря на то, что ядро Linux все еще официально представлялось бета-версией (уровня 0.99), оно было удивительно устойчивым. Размах и качество программного обеспечения в дистрибутивах Linux уже было таким же, как на действующих операционных системах.

Некоторые из Unix-разработчиков старой школы с более гибким мышлением стали отмечать, что долгожданная мечта о дешевой Unix-системе для каждого неожиданно начала воплощаться. Это происходило не благодаря AT&T, Sun или другому традиционному поставщику, и даже не благодаря организованным усилиям академических кругов. Это был бриколаж, созданный в Internet тем, что казалось спонтанным образованием, которое неожиданно заимствовало и комбинировало элементы Unix-традиции.

В стороне от этого процесса продолжалось корпоративное маневрирование. AT&T в 1992 году прекратила инвестировать Sun; затем в 1993 году продала свое подразделение Unix Systems Laboratories корпорации Novell. В 1994 году Novell передала торговую марку Unix группе разработки стандартов Х/Open. В том же году AT&T и Novell присоединились к OSF, наконец положив конец Unix-войнам. В 1995 году компания SCO приобрела UnixWare (и права на оригинальные исходные коды Unix) у Novell. В 1996 году организации Х/Open и OSF объединились, создав одну большую группу по разработке стандартов Unix.

Но традиционные поставщики Unix и последние сторонники противостояния казались все менее и менее значимыми. Активность и энергия в Unix-сообществе перемещалась к операционным системам Linux, BSD и разработчикам открытого исходного кода. К тому времени IBM, Intel и SCO анонсировали проект Monterey в 1998 году — последняя попытка объединить в одну большую систему все частные Unix-системы, оставшиеся "в стороне". Проект позабавил разработчиков и деловую прессу и внезапно прекратил существование в 2001 году после 3 лет движения в никуда.

Нельзя сказать, что промышленные транзакции были завершены до 2000 года, когда SCO продала UnixWare и оригинальные базовые исходные коды Unix компании Caldera, производителю дистрибутивов Linux. Но после 1995 года история Unix стала историей движения открытого исходного кода. У этой истории есть и другой аспект, и для того чтобы описать его, необходимо вернуться к событиям 1961 года и возникновению культуры Internet-хакеров.

 

2.2. Истоки и история хакерской культуры, 1961-1995 гг.

 

Unix-традиция является скрытой культурой, а не просто набором технических приемов. Она передает совокупность ценностей, касающихся красоты и хорошего дизайна; в ней есть свои легенды и народные герои. С историей Unix-традиции переплелась другая неявная культура, четко обозначить которую еще труднее. В ней также есть собственные ценности, легенды и народные герои, частично совпадающие с традициями Unix, а частично унаследованные из других источников. Чаще всего ее называют "хакерской культурой", и с 1998 года она почти совершенно совпадает с тем, что в деловой компьютерной прессе называется "движением открытого исходного кода" (the open source movement).

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

 

2.2.1. Академические игры: 1961 — 1980 гг.

Корни хакерской культуры прослеживаются до 1961 года, когда в MIT (Massachusetts Institute of Technology — Массачусетский технологический институт) появился первый мини-компьютер PDP-1. PDP-1 был одним из ранних интерак-тнвных компьютеров, и (в отличие от других машин) в то время был достаточно недорогим, поэтому время работы на нем жестко не регламентировалось. Он привлек к себе внимание группы любознательных студентов из клуба "Tech Model Railroad Club", которые из интереса проводили на нем эксперименты. В книге "Hackers: Heroes of the Computer Revolution" [46] увлекательно описаны ранние дни клуба. Наиболее известным их достижением была "SPACEWAR" — игра, сюжет которой состоял в вольной трактовке космической оперы "Lensman" Эдварда Эльмара "Док" Смита (Е.Е. "Doc" Smith)13

Несколько экспериментаторов из клуба TMRC позднее стали главными членами Лаборатории искусственного интеллекта Массачусетского технологического института (MIT Artificial Intelligence Lab), которая в 60-70-х годах прошлого века стала одним из мировых центров прогрессивной компьютерной науки. Они позаимствовали некоторые сленговые выражения и шутки клуба TMRC, в том числе традицию тонко (но безвредно) организовывать розыгрыши, которые назывались "hacks" ("шпильки"). Программисты лаборатории искусственного интеллекта, вероятнее всего, первыми стали называть себя "хакерами".

После 1969 года лаборатория MIT AI подключилась через сеть ARPANET к остальным ведущим научно-исследовательским компьютерным лабораториям: в Стэнфорде, лаборатории компании Bolt Beranek & Newman, лаборатории Университета Карнеги-Меллон (Carnegie-Mellon University, CMU) и др. Исследователи и студенты впервые ощутили, как сеть с быстрым доступом стирала географические границы, способствовала сотрудничеству и дружбе.

Программное обеспечение, идеи, сленг и юмор передавались по экспериментальным каналам ARPANET. Начало формироваться нечто похожее на коллективную культуру. Так, многие помнят еще о т.н. "файле жаргона" (Jargon File) — списке широко используемых сленговых терминов, который возник в Стэнфорде в 1973 году и неоднократно перерабатывался в Массачусетском университете после 1976 года. Он аккумулировал в себе сленг из CMU, Йельского университета и других центров ARPANET.

Ранняя хакерская культура с технической точки зрения почти полностью поддерживалась мини-компьютерами PDP-10. На них использовались различные операционные системы, которые впоследствии вошли в историю: TOPS-IO, TOPS-20, Multics, ITS, SAIL. Для программирования использовался ассемблер и диалекты LISP. Хакеры, работающие на PDP-10, взяли на себя поддержку самой сети ARPANET, поскольку других желающих выполнять эту работу не было. Позднее они стали основным кадровым составом IETF (Internet Engineering Task Force — инженерная группа по решению конкретной задачи в Internet) и основали традицию стандартизации посредством документов RFC (Requests For Comment — запросы на комментарии).

Это были исключительно талантливые молодые люди, чьим пристрастием стало программирование. Они склонялись к упорному отрицанию конформизма, спустя годы их будут называть "geeks" (помешанные). Они воспринимали компьютеры как устройства, создающие сообщество. Они читали Роберта Хейнлейна (Robert Heinlein) иТолкиена (J.R.R. Tolkien), играли в клубе "Общество творческого анахронизма" (Society for Creative Anachronism) и любили каламбуры. Несмотря на свои причуды (или, возможно, благодаря им), многие из них были в числе талантливейших программистов мира.

Они не были Unix-программистами. Unix-сообщество произошло в основном из той же массы "помешанных" в академических кругах, правительственных или коммерческих исследовательских лабораториях, однако эти культуры имели важные различия, которые были обусловлены слабой поддержкой сети в ранней Unix. До начала 80-х годов доступ к сети ARPANET на основе Unix практически не осуществлялся, и индивидуумы, входящие одновременно в оба лагеря, встречались нечасто.

Совместная разработка и совместное использование исходного кода было ценной тактикой для Unix-программистов. Для ранних ARPANET-хакеров, с другой стороны, это было больше, чем тактика. Для них это было скорее чем-то подобным общей религии, частично возникшей из академической идеи "опубликуй или погибни" (publish or perish) и (в наиболее крайних версиях) развившейся в почти шарденист-ский идеализм сетевых интеллектуальных сообществ. Наиболее известным представителем этой среды хакеров стал Ричард М. Столлмен.

 

2.2.2. Internet и движение свободного программного обеспечения: 1981—1991 гг.

После возникновения BSD-варианта TCP/IP в 1983 году началось взаимопроникновение культур Unix и ARPANET. Это стало вполне логичным результатом появления коммуникационных каналов, поскольку приверженцами обеих культур были в основном люди одного типа (а в действительности, зачастую те же люди). ARPANET-хакеры изучали С и начали употреблять жаргонные слова: каналы, фильтры и оболочки. Unix-программисты осваивали TCP/IP и стали называть друг друга "хакерами". Процесс слияния ускорился после того, как закрытие проекта Jupiter в 1983 году уничтожило будущее компьютеров PDP-10. К 1987 году две культуры сблизились настолько, что большинство хакеров программировали на С и небрежно использовали жаргон клуба "Tech Model Railroad Club" 25-летней давности.

(Если в 1979 году еще казались необычными прочные связи в обеих культурах, в Unix и ARPANET, то уже к середине 80-х годов они никого не удивляли. Когда в 1991 году автор этой книги расширил старый файл жаргона ARPANET в Новый словарь хакера (New Hacker's Dictionary) [66], две культуры практически смешались. Файл жаргона, созданный в ARPANET, но переработанный в Usenet, стал удачным символом этого слияния.)

Однако TCP/IP-сеть и сленг были не единственным наследием, которое после 1980 года хакерская культура получила благодаря своим "корням" в ARPANET. Эта культура стала неразрывно связана с именем Ричарда Столлмена.

Ричард М. Столлмен (широко известный под регистрационным именем RMS) к концу 1970 года уже доказал, что он является одним из наиболее способных современных программистов. Среди его многочисленных разработок был редактор Emacs. Для RMS закрытие проекта Jupiter в 1983 году только завершило дезинтеграцию культуры лаборатории MIT AI, которая началась несколькими годами ранее. RMS почувствовал себя изгнанным из хакерского рая и решил, что частное программное обеспечение достойно осуждения.

В 1983 году Столлмен основал проект GNU, целью которого было создание полностью свободной операционной системы. Хотя Столлмен никогда не был Unix-программистом, в условиях, создавшихся после 1980 года, реализация Unix-подобной операционной системы стала очевидной стратегией, которую следовало использовать. Большинство ранних помощников Столлмена были опытными ARPANET-хакерами, недавно влившимися в сообщество Unix.

В 1985 году Столлмен опубликовал Манифест GNU. В нем он сознательно создал идеологию из ценностей ARPANET-хакеров периода до 1980 года, полную новаторских этико-политических утверждений, независимых и характерных суждений. RMS ставил перед собой цель объединить рассеянное после 1980 года сообщество хакеров для достижения единой революционной цели. В его призывах явно прослеживались идеи Карла Маркса мобилизовать промышленный пролетариат против отчуждения результатов своего труда.

Манифест Столлмена разжег спор, который продолжается в хакерской среде и в наши дни. Его программа далеко выходила за рамки поддержки базового кода и, в сущности, подразумевала упразднение прав интеллектуальной собственности на программное обеспечение. Преследуя эту цель, Столлмен популяризировал понятие "свободное программное обеспечение" (free software), которое было первой попыткой определить продукт всей хакерской культуры. Столлмен написал Общедоступную лицензию (General Public License — GPL), которая должна была стать одновременно объединяющим началом и центром большой полемики по причинам, которые рассматриваются в главе 16. Дополнительные сведения, касающиеся позиции Столлмена и Фонда свободного программного обеспечения, приведены на Web-сайте проекта GNU .

Понятие "свободное программное обеспечение" было частично описанием и частично попыткой определения культурной индивидуальности для хакеров. До Столлмена представители хакерской культуры воспринимали друг друга как коллег-исследователей и использовали тот же сленг, однако никого не заботили споры о том, кем являются или должны быть "хакеры". После него в хакерской культуре стало ярче проявляться самосознание. Харизматическая и поляризованная фигура RMS оказалась в центре хакерской культуры, Столлмен стал ее героем и легендой. К 2000 году его уже едва ли можно было отличить от его легенды. В книге "Free as in Freedom" [90] дана превосходная оценка его имиджа.

Аргументы Столлмена повлияли даже на поведение многих хакеров, которые продолжали скептически относиться к его теориям. В 1987 году он убедил попечителей BSD Unix в целесообразности удаления частного кода AT&T с целью выпустить свободную версию. Однако, несмотря на его решительные усилия, в течение более чем 15 лет после 1980 года хакерская культура так и не объединилась вокруг его идеологии.

Другие хакеры заново обнаруживали для себя открытые, совместные разработки без секретов по более прагматическим и менее идеологическим причинам. В конце 80-х годов, в нескольких зданиях офиса Ричарда Столлмена в Массачусетском технологическом университете, успешно трудилась группа разработки системы X. Она финансировалась поставщиками Unix, которые убедили друг друга быть выше проблем контроля и прав интеллектуальной собственности вокруг системы X Window, и не видели лучшей альтернативы, чем оставить ее свободной для всех. В 1987-1988-х годах разработка системы X послужила прообразом действительно крупных распределенных сообществ, которые пятью годами позже заново определят наиболее развитый участок исследований Unix.

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

Х-разработчики не были последователями главного плана GNU, в то же время они не противодействовали ему активно. До 1995 года наиболее серьезное сопротивление плану GNU оказывали разработчики BSD. Приверженцы BSD, которые помнили, что они написали свободно распространяемое и модифицируемое программное обеспечение еще за годы до манифеста Столлмена, отвергали претензии проекта GNU на историческое и идеологическое главенство. Особенно они возражали против передающейся или "вирусной" собственности GPL, предлагая BSD-лицензию как "более свободную", поскольку она содержала меньше ограничений на повторное использование кода.

Это не помогало проекту Столлмена, и его попытки создания центральной части системы провалились, хотя его Фонд свободного программного обеспечения выпустил большую часть полного программного инструментария. Спустя 10 лет после учреждения проекта GNU, ядро GNU все еще не появилось. Несмотря на то, что отдельные средства, такие как Emacs и GCC, доказали свою потрясающую пользу, проект GNU без ядра не был способен ни угрожать гегемонии частных Unix-систем, ни предложить эффективное противодействие новой проблеме, связанной с монополией Microsoft.

После 1995 года спор вокруг идеологии Столлмена принял несколько иной оборот. Ее оппозиция стала ассоциироваться с именем Линуса Торвальдса, а также автора этой книги.

 

2.2.3. Linux и реакция прагматиков: 1991—1998 гг.

Даже когда проект HURD (GNU-ядро) "угасал", открывались новые возможности. В начале 90-х годов комбинация дешевых, мощных PC-компьютеров с простым Internet-доступом стала сильным соблазном для нового поколения молодых программистов, ищущих трудностей для испытания своего характера. Инструментарий пользователя, созданный Фондом свободного программного обеспечения, предложил весьма прогрессивный путь. Идеология следовала за экономикой, а не наоборот. Некоторые новички примкнули к крестовому походу Столлмена, приняв GNU в качестве его знамени, другим более импонировала традиция Unix в целом, и они присоединились к лагерю противников GPL, однако большинство вообще отказывалось от спора и просто писало код.

Линус Торвальдс искусно обошел противостояние, связанное с GPL, используя инструментальный набор GNU для окружения ядра Linux, созданного им, и лицензию GPL для его защиты, однако отказался от идеологической программы, которая следовала из лицензии Столлмена. Торвальдс заявлял, что в целом считает свободное программное обеспечение лучшим, чем частное, однако иногда использовал последнее. Его отказ становиться фанатиком даже в своем собственном деле делал его чрезвычайно привлекательным для большинства хакеров, которые чувствовали себя некомфортно под давлением разглагольствований Столлмена.

Жизнерадостный прагматизм Торвальдса и профессиональный, но скромный стиль, несомненно, способствовали удивительным победам хакерской культуры в 1993-1997 годах. Речь идет не только о технических успехах, но и о возникновении индустрии создания дистрибутивов, обслуживания и поддержки вокруг операционной системы Linux. В результате стремительно возрос его престиж и влияние. Торвальдс стал героем времени Internet. За 4 года (к 1995 году) он достиг таких "высот внутри культуры", для достижения которых Столлмену понадобилось 15 лет, причем он намного превзошел его рекорд в продаже "свободного программного обеспечения". В противоположность Торвальдсу, риторика Столлмена начала казаться резкой и неудачной.

Между 1991 и 1995 годами Linux перешла от тестовой среды, окружающей прототип ядра версии 0.1, к операционной системе, которая могла конкурировать по функциональности и производительности с частными Unix-системами, и превосходила их по таким важным характеристикам, как время непрерывной работы. В 1995 году Linux нашла свое приложение-приманку: Apache, Web-сервер с открытым исходным кодом. Как и Linux, Apache демонстрировал свою удивительную стабильность и эффективность. Linux-машины, поддерживающие Web-сервер Apache, быстро стали предпочтительной платформой для провайдеров Internet-услуг по всему миру; Apache поддерживает около 60 % Web-сайтов14 , умело обыгрывая обоих своих главных частных конкурентов.

Единственное, чего не предложил Торвальдс, это новая идеология — новый рациональный или генеративный миф хакерского движения, позитивное суждение, заменяющее враждебность Столлмена к интеллектуальной собственности программой, более привлекательной для людей как внутри, так и вне хакерской культуры. Автор данной книги невольно восполнил этот недостаток в 1997 году, пытаясь понять, почему Linux-разработка несколько лет назад не была дезорганизована. Технические заключения опубликованных статей [67] приведены в главе 19. Здась достаточно подчеркнуть, что при условии достаточно большого количества наблюдателей, все ошибки будут незначительными.

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

Контраст между "соборным" (т.е. централизованным, закрытым, контролируемым, замкнутым) и "базарным" (децентрализованным, открытым, с тщательной экспертной оценкой) видами разработки обусловил новое мышление данной среды. Это неразрывно связано с мнением Дуга Макилроя и Денниса Ритчи о братстве и обоюдном влиянии этого братства и ранних академических традиций ARPANET, связанных с экспертной оценкой и идеалистическими представлениями распределенного сообщества разума.

В начале 1998 года новое мышление подтолкнуло компанию Netscape Communications опубликовать исходный код браузера Mozilla. Внимание прессы к этому событию привело Linux на Уолл Стрит, способствовало возникновению бума акций технологических компаний в 1999-2000 годах, и действительно стало поворотной точкой, как в истории хакерской культуры, так и в истории Unix.

 

2.3. Движение открытого исходного кода: с 1998 года до настоящего времени

К моменту выхода браузера Mozilla в 1998 году хакерское сообщество наиболее правильно было бы охарактеризовать как множество группировок или братств. В него входили: движение свободного программного обеспечения Ричарда Столлмена, Linux-сообщество, Рег1-сообщество, BSD-сообщество, АрасЬе-сообщество, сообщество Х-разработчиков, Инженерная группа по решению конкретной задачи в Internet (IETF) и как минимум десяток других объединений. Причем эти группировки пересекались, и отдельные разработчики, весьма вероятно, входили в состав двух или более групп.

Братство могло формироваться вокруг определенного базового кода, который поддерживался его членами, вокруг одного или нескольких харизматических лидеров, вокруг языка или средства разработки, вокруг определенной лицензии на программное обеспечение или технического стандарта, или вокруг организации-попечителя для некоторой части инфраструктуры. Наиболее почитаемой является группа IETF, которая неразрывно связана с появлением ARPANET в 1969 году. BSD-сообщество, традиции которого формировались в конце 70-х годов, пользуется большим престижем, несмотря на меньшее, чем у Linux, количество инсталляций. Движение свободного программного обеспечения Столлмена, возникновение которого датируется началом 80-х годов, относится к числу старших братств, как по историческому вкладу, так и в качестве куратора нескольких интенсивно и повседневно используемых программных инструментов.

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

Поскольку хакерская культура после 1980 года "очень глубоко укоренилась" в Unix, новая миссия была неявным результатом триумфа Unix-традиции. Многие из старших лидеров хакерского сообщества, примкнувшие к Linux-движению, одновременно были ветеранами Unix, продолжающими традиции культурных войн 80-х годов после раздела AT&T.

Выход браузера Mozilla способствовал дальнейшему развитию идей. В марте 1998 года беспрецедентная встреча собрала влиятельных лидеров сообщества, представляющих почти все главные братства, для рассмотрения общих целей и тактики. В ходе этой встречи было принято новое определение общего для всех групп метода разработки: открытый исходный код (open source).

В течение 6 последующих месяцев почти все братства в хакерском сообществе приняли "открытый исходный код" как новое знамя. Более ранние группы, такие как IETF и BSD-разработчики, станут применять данное понятие ретроспективно к тому, что они делали до этого момента. Фактически к 2000 году риторика исходного кода будет не только объединять в хакерской культуре существующую практику и планы на будущее, но и представлять в новом свете свое прошлое.

Побудительный эффект от анонсирования продукта Netscape и новой важности Linux вышел далеко за пределы Unix-сообщества и хакерской культуры. Начиная с 1995 года, разработчики различных платформ, стоящих на пути Microsoft Windows (MacOS, Amiga, OS/2, DOS, CP/M, более слабые частные Unix-системы, различные операционные системы для мэйнфреймов, мини-компьютеров и устаревших микрокомпьютеров), сгруппировались вокруг языка Java, разработанного в Sun Microsystems. Многие недовольные Windows-разработчики присоединились к ним в надежде получить, по крайней мере, некоторую номинальную независимость от Microsoft. Однако поддержка Java со стороны Sun была (как описывается в главе 14) неумелой и разрозненной. Многим Java-разработчикам пришлось по вкусу то, что пропагандировалось в зарождающемся движении поддержки открытого исходного кода, и они йслед за Netscape перешли в сообщество Linux и открытого исходного кода, так же как ранее, следуя примеру Netscape, перешли к языку Java.

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

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

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

 

2.4. Уроки истории Unix

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

Анализируя прошлое, можно заключить, что это должно было стать очевидным гораздо раньше. Мы потеряли 10 лет после 1984 года, анализируя этот урок, и он, вероятно, является для нас слишком болезненным, чтобы его забыть.

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

Другой урок: никогда не следует противостоять дешевому и гибкому решению. Иными словами, низкоклассная/массовая аппаратная технология почти всегда в конце концов поднимает кривую мощности и выигрывает. Экономист Клейтон Кристенсен (Clayton Christensen) называет это пробивной технологией (disruptive technology) и в книге 'The Innovator's Dilemma" [12] демонстрирует, как это происходило с дисковыми накопителями, паровыми экскаваторами и мотоциклами. Мы видели это, когда мини-компьютеры заменили мэйнфреймы, рабочие станции и серверы сменили мини-компьютеры, а Intel-машины потребительского класса пришли на смену серверам и рабочим станциям. Движение открытого исходного кода выигрывает, потому что делает программное обеспечение потребительским товаром. Чтобы преуспеть, системе Unix необходимо выработать способность выбирать дешевое гибкое решение, а не пытаться бороться против него.

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

 

3 Контраст: сравнение философии Unix и других операционных систем

 

Если ваша проблема выглядит неприступной, найдите пользователя Unix, который покажет, как ее решить.
Информационный бюллетень Дилберта (Dilbert), 3.0, 1994 — Скотт Адаме

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

 

3.1. Составляющие стиля операционной системы

 

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

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

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

 

3.1.1. Унифицирующая идея операционной системы

В операционной системе Unix имеется несколько унифицирующих идей или метафор, которые формируют ее API-интерфейсы и определяемый ими стиль разработки. Наиболее важными из них, вероятно, являются модель, согласно которой "каждый объект является файлом", и метафора каналов (pipes)15 , построенная на ее поверхности. Как правило, стиль разработки в определенной операционной системе строго обусловлен унифицирующими идеями, которые были заложены в данную систему ее разработчиками. Они проникают в прикладное программирование из моделей, обеспеченных системными инструментами и API-интерфейсами.

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

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

 

3.1.2. Поддержка многозадачности

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

Для операционной системы более высокого уровня может быть характерна невытесняющая многозадачность (cooperative multitasking). Системы такого рода способны поддерживать множество процессов, однако при этом должно быть предусмотрено такое взаимодействие последних, когда один процесс произвольно "уступает" ресурсы процессора, прежде чем появится возможность запуска следующего процесса (таким образом, простые ошибки программирования могут привести к быстрой блокировке всей машины). Данный стиль операционных систем был временным переходным решением для аппаратного обеспечения, которое было достаточно мощным для поддержки конкурентных процессов, но испытывало либо недостаток периодических прерываний от таймера16 , либо недостаток в блоке управления памятью (memory-management unit), или то и другое. Многозадачность такого типа в настоящее время также является устаревшей и неконкурентоспособной.

В операционной системе Unix используется вытесняющая многозадачность (preemptive multitasking), при которой кванты времени распределяются системным планировщиком, который регулярно прерывает или вытесняет запущенный процесс для передачи управления следующему процессу. Почти все современные операционные системы поддерживают данный тип многозадачности.

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

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

 

3.1.3. Взаимодействующие процессы

В случае Unix малозатратное создание дочерних процессов (Process-Spawning) и простое межпроцессное взаимодействие (Inter-Process Communication — IPC) делают возможным использование целой системы небольших инструментов, каналов и фильтров. Данная система будет рассматриваться в главе 7; здесь необходимо указать некоторые последствия дорогостоящего создания дочерних процессов и IPC.

Канал был технически тривиален, но производил мощный эффект. Однако он никогда не стал бы простым без фундаментальной унифицирующей идеи процесса как автономной вычислительной единицы с программируемым управлением. В операционной системе Multics командный интерпретатор представлял собой просто другой процесс; управление процессами "не пришло свыше" вписанным в JCL.
Дуг Макилрой.

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

• Более естественным способом программирования становятся монолитные гигантские конструкции.

• Большая часть политики должна быть реализована внутри этих монолитов. Это подталкивает к использованию С++ и замысловатой многослойной внутренней организации кода, вместо С и относительно простых внутренних иерархий.

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

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

• Возникает необходимость изучения и использования асинхронного ввода-вывода.

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

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

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

Word, Excel, PowerPoint и другие программы Microsoft обладают детальными, можно сказать безграничными, знаниями о внутреннем устройстве друг друга. В Unix программист пытается разрабатывать программы не только для взаимодействия друг с другом, но и с еще не созданными программами.
Дуг Макилрой.

Данная тема также затрагивается в главе 7.

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

 

3.1.4. Внутренние границы

В Unix действует предположение о том, что программист знает лучше (чем система). Система не остановит пользователя и не потребует какого-либо подтверждения при выполнении опасных действий с данными, таких как ввод команды rm -rf *. С другой стороны, Unix весьма заботится о том, чтобы не допустить одного пользователя к данным другого. Фактически Unix побуждает пользователя иметь несколько учетных записей, в каждой из которых имеются собственные и, возможно, отличные от других записей привилегии, позволяющие пользователю обезопасить себя от аномально работающих программ17 . Системные программы часто обладают собственными учетными записями псевдопользователей, которые нужны для присвоения прав доступа только к определенным системным файлам без необходимости неограниченного доступа (или доступа с правами суперпользователя (superuser)).

В Unix имеется по крайней мере три уровня внутренних границ, которые защищают от злонамеренных пользователей или чреватых ошибками программ. Одним из таких уровней является управление памятью. Unix использует аппаратный блок управления памятью (Memory Management Unit — MMU), который препятствует вторжению одних процессов в адресное пространство памяти других. Вторым уровнем является реальное присутствие групп привилегий для множества пользователей. Процессы обычных пользователей (т.е. не администраторов) не могут без разрешения изменять или считывать файлы других пользователей. Третьим уровнем является заключение критичных к безопасности функций в минимально возможные участки благонадежного кода. В Unix даже оболочка (системный командный интерпретатор) не является привилегированной программой.

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

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

 

3.1.5. Атрибуты файлов и структуры записи

Unix-файлы не имеют ни структур записи (record structure), ни атрибутов. В некоторых операционных системах файлы имеют связанные структуры записи; операционная система (или ее служебные библиотеки) "знает" о файлах с фиксированной длиной записи или об ограничивающем символе текстовой строки, а также о том, следует ли читать последовательность CR/LF как один логический символ.

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

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

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

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

 

3.1.6. Двоичные форматы файлов

Если в операционной системе применяются двоичные форматы для важных данных (таких как учетные записи пользователей), вполне вероятно, что традиции использования читабельных текстовых форматов для приложений не сформируются. Более подробно о том, почему данный подход является проблемным, будет сказано в главе 5. Здесь достаточно упомянуть о нескольких последствиях.

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

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

Для проектирования системы, полностью противоположной Unix, нужно сделать все форматы файлов двоичными и неясными, а также сделать обязательным использование тяжеловесных инструментов для их чтения и редактирования.

 

3.1.7. Предпочтительный стиль пользовательского интерфейса

В главе 11 подробно рассматриваются различия между интерфейсами командной строки (Command-Line Interfaces — CLI) и графическими пользовательскими интерфейсами (Graphical User Interfaces — GUI). Выбор проектировщиком операционной системы одного из этих типов в качестве обычного режима представления влияет на многие аспекты конструкции от планирования процессов и управления памятью до программных интерфейсов приложений (Application Programming Interfaces — API), предоставленных приложениям для использования.

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

Если в операционной системе CLI-средства являются слабыми или их вообще нет, то проявляются описанные ниже последствия.

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

• Удаленное системное администрирование будет слабым и трудным в использовании, и будет потреблять больше сетевых ресурсов18 .

• Даже простые неинтерактивные программы будут нести на себе издержки графического интерфейса или замысловатого интерфейса сценариев.

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

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

 

3.1.8. Предполагаемый потребитель

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

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

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

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

Это скорее следствие, чем цель. Я испытываю отвращение к системе, разработанной для "пользователя", если в слове "пользователь" закодировано уничижительное значение "тупой и примитивный".
Кен Томпсон.

Для того чтобы разработать операционную систему, абсолютно противоположную Unix, ее нужно писать так, как будто она "знает" о намерениях пользователя больше, чем он сам.

 

3.1.9. Входные барьеры для разработчика

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

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

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

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

Любительское программирование зародилось в Unix. Одним из новшеств, которое впервые появилось в Unix, была поставка компилятора и инструментов написания

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

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

 

3.2. Сравнение операционных систем

 

Логика выбора конструкции Unix становится более очевидной в сравнении с другими операционными системами. Ниже приводится только общий обзор конструкций19 .

На рис. 3.1. отражены генетические связи между рассматриваемыми операционными системами разделения времени. Несколько других операционных систем (отмеченные серым цветом и не обязательно являющиеся системами разделения времени) включены для расширения контекста. Системы, названия которых обрамлены сплошными линиями, до сих пор существуют. Дата "рождения" представляет собой дату первой поставки20 , дата "смерти", как правило, — это дата, когда поставщик прекратил поставку системы.

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

Блок "Unix" включает в себя все частные Unix-системы, включая AT&T и ранние версии Berkeley Unix. Блок "Linux" включает в себя Unix-системы с открытыми исходными кодами, каждая из которых была основана в 1991 году. Они имеют генетическую наследственность от раннего Unix-кода, который был освобожден от частного контроля AT&T соглашением по судебному процессу 1993 года.

 

3.2.1. VMS

VMS — частная операционная система, первоначально разработанная для мини-компьютера VAX корпорации "Digital Equipment Corporation" (DEC). Впервые она была выпущена в 1978 году и была важной действующей операционной системой в 80-х и начале 90-х годов. Сопровождение данной системы продолжалось, когда DEC была приобретена компанией Compaq, а последняя — корпорацией Hewlett-Packard.

На момент написания книги операционная система VMS продолжала продаваться и поддерживаться. VMS приведена в данном обзоре для демонстрации контраста между Unix и другими CLI-ориентированными операционными системами эры мини-компьютеров.