The Evolution of the Unix Time-sharing System*
- Dennis M. Ritchie
Bell Laboratories, Murray Hill, NJ, 07974
ABSTRACT
Документ представляет краткое описание начального этапа разработки операционной системы UNIX.
Более детально рассматривается развитие файловой системы,
механизма управления процессами.
Уделено внимание социальным условиям,на фоне которых разрабатывалась система.
-
-
NOTE: *This paper was first presented at the Language
Design and Programming Methodology conference at Sydney,
Australia, September 1979.
The conference proceedings were published as
Lecture Notes in Computer Science #79:
Language Design and Programming Methodology,
Springer-Verlag, 1980.
This rendition is based on a reprinted version appearing in
AT&T Bell Laboratories Technical Journal
63
No. 6 Part 2, October 1984, pp. 1577-93.
-
Введение
За последние годы UNIX становится одним из самых популярных символов в мире.
Вообще, Unix родился в 1969 , а не в 1974, как это приянято считать,
и это мало-известная история.
В этом документе будет представлена техническая и социальная сторона
раннего этапа эволюциии UNIX.
Начало
В 1968-1969 гг. Bell Laboratories переживала не лучшие времена.
Подразделение , занимающееся проектом Multics , испытывало проблемы.
Перспективы его развития уперлись в расширение функционала.
К тому же в отделах компьютерных исследований начался организационный раздрай.
Группа разработчиков , которые находились у истоков развития Unix
(K. Thompson, Ritchie, M. D. McIlroy, J. F. Ossanna),
фактически были свидетелями и участниками процесса под названием - закат Multics.
Ее ограниченные возможности по-прежнему были нам доступны,
и она оказалась тем связующим звеном,которая обьединила нашу коммуну .
В 1969 году мы начали искать альтернативу Multics.
Нам нужна была машина для написания новой операционной системы.
Таких машин было две - DEC PDP-10 и SDS (later Xerox) Sigma 7.
Нам нужна была прежде всего финансовая поддержка такого проекта.
Все наши попытки в итоге оказались пресечены ,
и вице-президент нашей компании W. O. Baker заявил :
'В Bell Laboratories так дела не делаются !'
Ситуация была стандартной - мы просили слишком больших денег на слишком неопределенные сроки.
Разработка операционных систем в то время было делом вообще непонятным и непривлекательным.
Наше участие в запуске центра вычислений также оказалось под вопросом.
Что касается технических аспектов:
на фоне всего этого Thompson, R. H. Canaday, Ritchie занимались базовой разработкой файловой системы,
которая позже стала сердцевиной Unix.
Основную работу выполнял Thompson,
мне принадлежала идея device files.
Томсон создал на Multics модель поведения этой файловой системы
на фоне выполнения процессов.
Параллельно он начал работу над новой операционной системой для машины
GE-645, писал ассемблер и в рудиментарной форме ядро операционной системы.
Но вскоре стало ясно , что лаборатория 645 доживает последние месяцы в стенах Bell Laboratories.
В том же 1969-м году Thompson разрабатывал игру под названием
`Space Travel.'
Вначале она была написана для Multics, затем переведена на Fortran
для GECOS(ось для GE, Honeywell, 635),
это был симулятор движения небесных тел,с руководством по игре,
с попытками приземления на всякие планеты.
GECOS не устраивала по нескольким причинам:
контроль был плохо управляем , каждую команду приходилось набирать,
да и сама игра стоила $75 только за то , чтобы в нее поиграть !
В результате Thompson откопал маленький PDP-7 с отличным дисплеем и графическим терминалом.
Мы с ним переписали Space Travel для этой машины.
Пришлось написать целый пакет для floating-point вычислений,
а также дебаггер , который выводил отладочную информацию во время игры в уголке экрана.
Все естественно было написано на ассемблере ,
был использован cross-assembler все той же GECOS.
Space Travel оказался подготовительным плацдармом для перехода PDP-7.
Thompson начал реализовывать для нее файловую систему.
Сама по себе файловая система без прикладного применения представляла небольшой интерес.
Были написаны утилиты для манипулирования файлами:
копирование,печать,удаление,редактирование,
и конечно командный интерпретатор (shell).
Программы были сохранены для PDP-7 на бумажную ленту;
ассемблер уже был способен поддерживать систему.
Так в 1970 появился зародыш UNIX ,
само слово которое представляет из себя каламбур на тему `Multics'.
Юниксовая файловая система для PDP-7
Вообще говоря,файловая система PDP-7 была похожа на нонешнюю.
В ней были
- 1)
-
i-list: линейный массив нод - i-nodes -
каждая нода с описанием одного файла.
Нода включала меньше информации,чем сейчас,но основное в ней уже было:
уровень защиты файла, тип и размер, а также список физических блоков,хранящих его контент.
- 2)
-
Директории : специальная разновидность файлов,включающих последовательность имен.
- 3)
-
Специальные файлы устройств.В них не было нод,но был специальный номер.
Основные системные файловые вызовы были представлены с самого начала:
Read, write, open, creat (sic), close,
в этой форме они существуют и до сих пор.
Отличием было то , что I/O работал на уровне слов , а не байт,
поскольку у PDP-7 была word-addressed архитектура.
В связи с чем в потоках напрочь игнорировались нулевые символы.
Терминал также был несовершенен в плане управления жизнью создаваемых им процессов.
В файловой системе PDP-7 было отличие:
пути к файлам отсутствовали.
Линка в обычном юниксовом понимании не было.
Вызов
link
имел форму
link(dir, file, newname)
где
dir
был текущим каталогом файла,
file
был именем,
и
newname
было именем линка, который добавлялся к текущей директории.
Файловая система PDP-7 имела форму направленного графа.
Поддержка линков для пользователей была не нужна.
Был каталог под названием
dd
который являлся текущим каталогом пользователя.
Для того чтобы сделать линк на какой-то файл
x
в каталоге
ken,
нужно было выполнить
ln dd ken ken
ln ken x x
rm ken
Невозможно было создать новый каталог , потому что первоначально
все каталоги хранились на бумажном носителе.
Для смены каталога использовалась команда
chdir
с тучей аргументов.Команда
chdir dd ken
перемещала в каталог
ken.
Отсутствие путей,невозможность создать новый каталог,
сложность инсталляции нового устройства - это все были минусы данной системы.
Реализация этой операционной системы не была мульти-программной.
Только одна программа могла выполняться за раз ,
и передача управления другой программе была возможна во время выполнения явного свопа.
Например , была такая утилита
iget,
которая предоставляла доступ к ноде.
Она возвращала константу вместо того , чтобы вернуть указатель на таблицу активных нод.
Диск в PDP-7 был быстр для того времени;
он пропускал 18-битное слово за 2 микросекунды.
С другой стороны, у PDP-7 цикл памяти был равен 1 миллисекунде,
а большинство инструкций имело 2 цикла (один на себя,другой на операнд).
Непрямая адресация уже требовала 3 цикла и была довольно медленной,
поскольку в машине не было индексных регистров.
DMA controller был очень медленным.
Диск постоянно генерил ошибки при непрямой адресации.
Контроль за процессами
Под этим я понимаю механизм,с помощью которого создаются и используются процессы.
Под этим понимаются системные вызовы
fork,
exec,
wait,
exit.
Как работает shell :
- 1)
-
shell читает строку с терминала.
- 2)
-
Он создает дочерний процесс с помощью
fork.
- 3)
-
Дочерний процесс использует
exec
для загрузки из файла.
- 4)
-
shell контролирует дочерний процесс с помощью wait,
чтобы в случае чего прибить его с помощью
exit.
- 5)
-
Далее shell возвращается на шаг 1).
В ранней версии PDP-7 Unix было 2 процесса - по числу терминалов.
Не было
fork,
wait,
exec.
Был только
exit,
shell работал по принципу :
- 1)
-
shell закрывал все открытые файлы, затем открывал специальный терминальный файл
для стандартного ввода-вывода
(файловые дескрипторы 0 и 1).
- 2)
-
Читал команду с терминала.
- 3)
-
Открывался файл,затем специальный загрузчик копировал этот файл в память , далее ему передавалось
управление.
- 4)
-
Когда в терминале набиралась команда,процесс убивался путем вызова
exit.
Вызов
exit
загружал по новой shell, которому опять передавалось управление.
В этой моделии shell выступал как пользовательская программа ,
а не часть операционной системы.
Такая схема управления - по одному процессу на терминал -
использовалась в CTSS, Multics, Honeywell TSS, IBM TSS .
Не было каталога /dev , поскольку путей вообще не было.
Позднее появилась конвенция , которая гласила:
каждый каталог должен иметь точку входа - tty.
Контроль над процессами в его нонешней форме был реализован за пару дней.
Было произведено разделение между системными вызовами
fork
и
exec.
В юниксе форкнутый поцесс начинает выполняться в том же адресном пространстве,
в котором выполняется его родитель.
Для Томпсона это не было в диковинку,
поскольку это уже было реализовано в системе Беркли.
Система научилась управлять как минимум 2 процессами.
Появилась таблица процессов,
появился своппинг процессов.
Эта реализация fork предусматривала :
- 1)
-
Расширение таблицы процессов
- 2)
-
текущий процесс копировался в disk swap area,
используя уже существующие функции swap IO
Реализация fork на PDP-7
потребовала 27 строчек ассемблерного кода.
Были и другие изменения как в самой операционной системе , так и в пользовательских программах.
И появление комбинации
fork-exec
было использовано в существующем shell.
Системный вызов
exit
был доработан:
теперь он очищал строку в таблице процессов и передавал контроль , а не создавал новый shell.
Между процессами появилась возможность обмениваться сообщениями в слово:
smes(pid, message)
(pid, message) = rmes()
Это давало возможность обмениваться сообщениями не только процессам,
которые были связаны как parent-child.
Родительский shell после создания нового процесса
посылал ему сообщение с помощью
smes;
и когда этот порожденный процесс умирал,
тот же smes возвращал терминалу ошибку , что процесс помер.
По сути , это было зародышем будущего
wait.
Стартовому процессу был присвоен ID-шник под номером 1 ,
он создавал shell для каждого присоединенного к машине терминала,
а каждый shell в ответ посылал сообщение этому процессу,подтверждая коннект.
В этой системе были и недостатки.
Если shell посылал сообщение какому-то процессу,
он мог подвиснуть до тех пор , пока не получал ответа ,
это нарушало синхронизацию в работе терминала.
Одним из преимуществ в таком управлении процессами
в частности была возможность рекурсивного вызова shell.
При реализации такой схемы multiple-process появились свои баги.
В частности , перестала работать команда chdir(change current directory).
Оказалось , что в старой системе текущий каталог процесса приаттачивался к терминалу.
А в новой системе каталог изменялся при создании процесса,
но сам процесс прибивался.
Нужно было переписать команду
chdir
и выполнять ее внутри shell.
Этим свойством были наделены и некоторые другие команды , такие как
login.
Другая проблема возникла , когда новый создаваемый процесс ассоциировался с каким-то файлом,
и указатель на этот файл хранился внутри самого процесса.
Это вылезло боком при создании командных файлов
Предположим командный файл состоит из 2-х команд:
ls
who
и он выдает :
sh comfile >output
Цепочка событий
- 1)
-
Главный shell создает новый процесс, который открывает
outfile
для получения вывода и запуска рекурсивно еще одного shell.
- 2)
-
Новый shell создает новый процесс для запуска ls,
который выводит
output
и умирает.
- 3)
-
Создается еще один процесс для следующей команды.
Указатель IO для output равен 0, поскольку shell ничего не писал
в output.
В результате
who
перезаписывает поверх старого output свои собственные результаты.
Для решения этой проблемы надо было создать новую системную таблицу
указателей IO открытых файлов независимо от процессов,
которыми они были созданы.
IO Redirection
Удобная нотация для указания направления операций IO : символы `>' и `<'
- не было в ранней версии PDP-7 Unix.
Но эта система появилась еще в Multics.
В Multics был возможность реализовать механизм IO потоков,
которые можно было динамически перенаправить на устройства,файлы
или специальные потоковые модули.
Unix-команда
ls >xx
для получения списка файлов в каталоге
xx,
была равнозначна в Multics команде
iocall attach user_output file xx
list
iocall attach user_output syn user_i/o
Но эта возможность в Multics не была использована,
поскольку за разработку IO system в Bell Labs отвечал Murray Hill,
а shell занималась другая команда.
Но поскольку Unix IO system и его shell
оказались в ведении одного человека - Thompson,
эта идея и была им реализована.
Рождение PDP-11
В начале 1970,
мы предложили приобрести PDP-11, который только что был проанонсирован Digital.
У нас появилась бездисковая версия этой машины в мае 1970-го года.
Рудиментарный линукс был написан для него с помощью cross-assembler PDP-7.
Первая PDP-11 система
Как только мы получили диск,система стала быстро наполняться.
Первая версия не была даже мульти-программной.
Но зато появилась структура директорий с полными путями.
Было всего 24 (!) килобайта памяти , из них 16 отводилось системе и 8 на пользовательские программы.
Диск состоял из одного физического блока (512 кило-байт), файлы были ограничены 64 кило-байтами.
Дальше развитие PDP-11 пошло в прикладном направлении -
в плане создания системы обработки ткста - word text processor -
таковы были реалии рабочей обстановки.
К весне 1971 мы прекратили системные изыскания в области Unix.
Мы перевели текстовой форматер-транслятор по имени
roff
на ассемблер PDP-11,
который передрали с версии McIlroy's BCPL Multics,
который в свою очередь был передран с программы
J. Saltzer's
runoff
на платформе CTSS :-)
Мы представили текст-форматный сервис в патентную службу
для подготовки патентной документации.
Была параллельно реализована коммерческая версия этой программы:
была реализована телетайпная модель с 37 терминалами.
Во второй половине 1971 года в патентное бюро были представлены
три версии для набора,редактирования и форматирования патентной документации.
После чего мы смогли вернуться к нашим изысканиям в области Unix.
На машине, у которой не было никакой защиты памяти и один диск на .5 MB ,
любой тест новой программы мог накрыть медным тазом всю систему.
Эксперимент , как вы уже догадались , удался.
Юникс пустил корни не только в патентном управлении,
но и во многих других лабораториях нашей компании.
На этой волне была приобретена очередная PDP 11/45.
К тому времени мы уже успели опубликовать результаты нашей работы
( [1, 5, 6, 7, 8, 9]).
Pipes
One of the most widely admired contributions of Unix
to the culture of operating systems and command languages
is the
pipe,
as used in a pipeline of commands.
Of course, the fundamental idea was by no means new;
the pipeline is merely a specific form of coroutine.
Even the implementation was not unprecedented,
although we didn't know it at the time;
the `communication files' of the Dartmouth
Time-Sharing System [10]
did very nearly what Unix pipes do,
though they seem not to have been exploited so fully.
Pipes appeared in Unix in 1972,
well after the PDP-11 version of the system was in operation,
at the suggestion (or perhaps insistence) of M. D. McIlroy,
a long-time advocate of the non-hierarchical control flow
that characterizes coroutines.
Some years before pipes were implemented, he suggested
that commands should be thought of as binary operators,
whose left and right operand specified the input and output files.
Thus a `copy' utility would be commanded by
inputfile copy outputfile
To make a pipeline, command operators could be stacked up.
Thus, to sort
input,
paginate it neatly, and print the result off-line,
one would write
input sort paginate offprint
In today's system, this would correspond to
sort input | pr | opr
The idea, explained one afternoon on a blackboard,
intrigued us but failed to ignite any immediate action.
There were several objections to the idea as put:
the infix notation seemed too radical (we were too
accustomed to typing `cp x y' to copy
x
to
y);
and we were unable to see how to
distinguish command parameters from the input or output files.
Also, the one-input one-output model
of command execution seemed too confining.
What a failure of imagination!
Some time later, thanks to McIlroy's persistence,
pipes were finally installed in the operating system
(a relatively simple job),
and a new notation was introduced.
It used the same characters as for I/O redirection.
For example, the pipeline above might have been written
sort input >pr>opr>
The idea is that following a `>' may be either a file,
to specify redirection of output to that file,
or a command into which the output of the preceding command
is directed as input.
The trailing `>' was needed in the example to specify
that the (nonexistent) output of
opr
should be directed
to the console; otherwise the command
opr
would not have been executed at all;
instead a file
opr
would have been created.
The new facility was enthusiastically received, and
the term `filter' was soon coined.
Many commands were changed to make them usable in pipelines.
For example, no one had imagined that anyone would want the
sort
or
pr
utility to sort or print its standard input if given no explicit arguments.
Soon some problems with the notation became evident.
Most annoying was a silly lexical problem:
the string after `>' was delimited by blanks, so,
to give a parameter to
pr
in the example, one had to quote:
sort input >"pr -2">opr>
Second, in attempt to give generality,
the pipe notation accepted `<' as an input redirection
in a way corresponding to `>'; this meant that the notation was
not unique.
One could also write, for example,
opr <pr<"sort input"<
or even
pr <"sort input"< >opr>
The pipe notation using `<' and `>' survived
only a couple of months;
it was replaced by the present one
that uses a unique operator
to separate components of a pipeline.
Although the old notation had a certain charm and
inner consistency,
the new one is certainly superior.
Of course, it too has limitations.
It is unabashedly linear, though there are situations
in which multiple redirected inputs and outputs
are called for.
For example, what is the best way to compare the outputs of
two programs?
What is the appropriate notation for invoking a program
with two parallel output streams?
I mentioned above in the section on IO redirection that Multics
provided a mechanism by which IO streams could be directed
through processing modules on the way to (or from) the device
or file serving as source or sink.
Thus it might seem that stream-splicing in Multics
was the direct precursor of Unix pipes, as Multics
IO redirection certainly was for its Unix version.
In fact I do not think this is true, or is true only in a weak sense.
Not only were coroutines well-known already,
but their embodiment as Multics spliceable IO modules
required that the modules be specially coded in such a way
that they could be used for no other purpose.
The genius of the Unix pipeline is precisely that it
is constructed from the very same commands used constantly
in simplex fashion.
The mental leap needed to see this possibility
and to invent the notation is large indeed.
High-level languages
Every program for the original PDP-7 Unix system was written in
assembly language, and bare assembly language it wasfor example,
there were no macros.
Moreover, there was no loader or link-editor, so every program had to be complete in itself.
The first interesting language to appear was a version
of McClure's TMG [11]
that was implemented by McIlroy.
Soon after TMG became available,
Thompson decided
that we could not pretend to offer a real computing service
without Fortran,
so he sat down to write a Fortran in TMG.
As I recall,
the intent to handle Fortran lasted about a week.
What he produced instead was a definition of and a compiler for
the new language B [12].
B was much influenced by the BCPL language [13];
other influences were Thompson's taste for spartan syntax,
and the very small space into which the compiler had to fit.
The compiler produced simple interpretive code;
although it and the programs it produced were rather slow,
it made life much more pleasant.
Once interfaces to the regular system calls were made available,
we began once again to enjoy the benefits of using a reasonable
language to write what are usually called
`systems programs:'
compilers, assemblers, and the like.
(Although some might consider the PL/I we used under
Multics unreasonable,
it was much better than assembly language.)
Among other programs, the PDP-7 B cross-compiler for the PDP-11
was written in B, and in the course of time,
the B compiler for the PDP-7 itself was transliterated
from TMG into B.
When the PDP-11 arrived,
B was moved to it almost immediately.
In fact, a version of the multi-precision `desk calculator'
program
dc
was one of the earliest programs to run on the PDP-11,
well before the disk arrived.
However, B did not take over instantly.
Only passing thought was given to rewriting the operating system
in B rather than assembler,
and the same was true of most of the utilities.
Even the assembler was rewritten in assembler.
This approach was taken mainly because of the slowness of the interpretive
code.
Of smaller but still real importance was the mismatch
of the word-oriented B language with the byte-addressed
PDP-11.
Thus, in 1971, work began on what was to become the C language [14].
The story of the language developments from BCPL
through B to C is told elsewhere [15],
and need not be repeated here.
Perhaps the most important watershed occurred during 1973,
when the operating system kernel was rewritten in C.
It was at this point that the system assumed its modern form;
the most far-reaching change was the introduction of
multi-programming.
There were few externally-visible changes, but the internal structure of the
system became much more rational and general.
The success of this effort convinced us that C was useful
as a nearly universal tool for systems programming,
instead of just a toy for simple applications.
Today, the only important Unix program still written in assembler
is the assembler itself;
virtually all the utility programs are in C,
and so are most of the applications programs, although there are
sites with many in Fortran, Pascal, and Algol 68 as well.
It seems certain that much of the success of Unix follows
from the readability, modifiability, and portability
of its software that in turn follows
from its expression in high-level languages.
Conclusion
One of the comforting things about old memories is their tendency
to take on a rosy glow.
The programming environment provided by the early versions of Unix seems,
when described here, to be extremely harsh and primitive.
I am sure that if forced back to the PDP-7 I would find it intolerably limiting and
lacking in conveniences.
Nevertheless, it did not seem so at the time;
the memory fixes on what was good and what lasted, and on the joy of helping
to create the improvements that made life better.
In ten years, I hope we can look back with the same mixed impression
of progress combined with continuity.
Acknowledgements
I am grateful to S. P. Morgan, K. Thompson, and M. D. McIlroy
for providing early documents and digging up recollections.
Because I am most interested in describing the evolution
of ideas, this paper attributes ideas and work to individuals only where
it seems most important.
The reader will not, on the average,
go far wrong if he reads each occurrence of `we'
with unclear antecedent
as `Thompson, with some assistance from me.'
References
- 1.
-
D. M. Ritchie and K. Thompson,
`The Unix Time-sharing System,
C. ACM
17
No. 7 (July 1974), pp 365-37.
- 2.
-
L. P. Deutch and B. W. Lampson,
`SDS 930 Time-sharing System Preliminary
Reference Manual,' Doc. 30.10.10, Project Genie,
Univ. Cal. at Berkeley (April 1965).
- 3.
-
R. J. Feiertag and
E. I. Organick,
`The Multics input-output system,'
Proc. Third Symposium on Operating Systems Principles,
October 18-20, 1971,
pp. 35-41.
- 4.
-
The Multiplexed Information and Computing Service: Programmers' Manual,
Mass. Inst. of Technology, Project MAC, Cambridge MA, (1969).
- 5.
-
K. Thompson,
`Unix Implementation,'
Bell System Tech J.
57
No. 6, (July-August 1978), pp. 1931-46.
- 6.
-
S. C. Johnson and D. M. Ritchie,
Portability of C Programs and the Unix System,'
Bell System Tech J.
57
No. 6, (July-August 1978), pp. 2021-48.
- 7.
-
B. W. Kernighan,
M. E. Lesk, and
J. F. Ossanna.
`Document Preparation,'
Bell Sys. Tech. J.,
57
No. 6,
pp. 2115-2135.
- 8.
-
B. W. Kernighan and
L. L. Cherry,
`A System for Typesetting Mathematics,'
J. Comm. Assoc. Comp. Mach.
18,
pp. 151-157
(March 1975).
- 9.
-
M. E. Lesk and
B. W. Kernighan,
`Computer Typesetting of Technical Journals on Unix,'
Proc. AFIPS NCC
46
(1977), pp. 879-88.
- 10.
-
Systems Programmers Manual for the Dartmouth Time Sharing System for the GE 635 Computer,
Dartmouth College,
Hanover, New Hampshire,
1971.
- 11.
-
R. M. McClure,
`TMG--A Syntax-Directed Compiler,'
Proc 20th ACM National Conf. (1968), pp. 262-74.
- 12.
-
S. C. Johnson and B. W. Kernighan,
`The Programming Language B,'
Comp. Sci. Tech. Rep. #8, Bell Laboratories,
Murray Hill NJ (1973).
- 13.
-
M. Richards,
`BCPL: A Tool for Compiler Writing and Systems Programming,'
Proc. AFIPS SJCC
34
(1969), pp. 557-66.
- 14.
-
B. W. Kernighan and
D. M. Ritchie,
The C Programming Language,
Prentice-Hall, Englewood Cliffs NJ, 1978.
Second Edition, 1979.
- 15.
-
D. M. Ritchie, S. C. Johnson, and M. E. Lesk,
`The C Programming Language,'
Bell Sys. Tech. J.
57
No. 6
(July-August 1978) pp. 1991-2019.
Copyright 1996 Lucent Technologies Inc. All rights reserved.
Интервью с Кеном Томпсоном
Когда-то в одном интервью на вопрос, что бы вы изменили, если бы
пришлось еще раз создавать Unix, вы ответили: <<добавил бы букву e к
системному вызову creat>>. А если серьезно, учитывая, что это все в
прошлом, можете ли вы сказать, какие трудности вы преодолели,
рассказать об оригинальных решениях и о том, что сегодня сделали бы
по-другому.
Я думаю, что самое важное и замечательное качество в Unix состоит в
том, что в ней реализован ясный и простой интерфейс: открыть, закрыть,
прочитать и записать. Такой подход позволил реализовать shell, а также
обеспечить переносимость Unix. В ранних системах ввод/вывод имел
различные точки ввода, но с помощью Unix вы можете от них
абстрагироваться. Вы открываете файл, и, если он оказался на ленте,
можете в него писать. Каналы дали возможность использовать
инструментальные средства и фильтры, которые позволили адаптировать
классические громоздкие программы, такие как сортировка.
Вероятно, самая серьезная наша ошибка была в том, что мы недооценили
концепцию удаленности. Интерфейс типа
открыть-закрыть-прочитать-записать должен был быть инкапсулирован
воедино, как нечто, ориентированное на удаленность; нечто, что
связывало бы в одно целое группу интерфейсов - удаленную файловую
систему, а не локальную файловую систему.
В Unix этой концепции нет; здесь была лишь одна группа интерфейсов
типа открыть-закрыть-прочитать-записать. Это оказалось заметным
упущением и послужило причиной появления в Unix таких неприятных
вещей, как ptrace и некоторые из системных вызовов. Каждый раз, когда
мне попадаются последние версии Unix, я обнаруживаю 15 новых системных
вызовов. Я больше не обращаю на это внимания. Это уже было исправлено
в Plan 9.
Давайте вернемся чуть дальше в прошлое. Какие черты Multics были
использованы для логического обоснования архитектуры Unix?
Я позаимствовал только одно: иерархическую файловую систему, различие
состояло в том, что Multics была системой виртуальной памяти и эти
<<файлы>> были не файлами, а своеобразными правилами именования
сегментов. Попав в одно из иерархических пространств имен, которые
были подключены извне и на самом деле не являлись частью системы,
пользователь обращался к нему и они становились частью его адресного
пространства, а затем он использовал машинные команды для сохранения
данных в этом сегменте. Я совершенно откровенно это позаимствовал.
Кроме того, Multics была системой виртуальной памяти со страничными
прерываниями и не различала страницы данных и страницы программ. Вы
переходили на сегмент, возвращаемый по страничному прерыванию, вне
зависимости от того, были это данные или команды. Не было файлов,
которые можно было читать или записывать - ничего, что бы вы могли
передавать на удаленную систему. На мой взгляд, это недостаток.
Огромное пространство виртуальной памяти являлось унифицированной
концепцией, лежащей в основе Multics (и ее нужно было попробовать в
эпоху, когда все стремились создать единую теорию программирования),
хотя я считаю, что это было серьезной ошибкой.
Мне захотелось отделить данные от программ, поскольку данные и команды
друг от друга сильно отличаются. Читая файл, вы почти всегда уверены,
что данные будут читаться последовательно, и вас не удивляет, что вы
можете загрузить a и прочитать затем a + 1. Более того, извлекать из
кэш команды намного сложнее, чем данные. Поэтому я добавил системный
вызов exec, который указывает <<запустите это как программу>>, в то
время как в Multics вы должны были <<прерваться>> по отсутствию
требуемой команды и перейти на нее.
История разработки
Расскажите немного о том, как создавался Unix.
В первых версиях по существу экспериментировал с некоторыми
концепциями Multics на PDP-7 после того, как проект был закрыт. Я
работал с такой маленькой командой, какую вы только можете себе
представить. Затем я выбрал двоих пользователей, Дуга Макилроя и
Денниса Ричи, которых интересовали языки. Выслушав их замечания, очень
профессиональные и точные, я был вынужден разработать еще пару
вариантов на ассемблере PDP-7.
В какой-то момент я получил от Мартина Ричардса из Массачусетского
технологического института BCPL и преобразовал его в то, что считал
довольно прямым переводом, но на самом деле получился иной язык,
который я назвал Би. Затем Деннис добавил к нему типы и назвал его Си.
Мы купили PDP-11 - одну из самых первых машин - и я переписал Unix на
ассемблере PDP-11, получив работоспособную версию. Она использовалась
для некоторых внутренних телефонных приложений корпорации Bell, для
сбора отчетов о неисправностях и контроля различных вещей, в частности
кабелей, размещение которых менялось. Эти приложения так или иначе
требовали поддержки со стороны операционной системы. Их необходимо
было обслуживать, поэтому в Bell Labs была создана специальная группа
Unix Support Group. Она должна была служить своего рода интерфейсом
связывать наши версии с приложениями в предметной области, которым
была необходима более стабильная среда. Они не казались чем-то
неожиданным. Со временем они были преобразованы в коммерческую версию
компании AT&T и более автономную версию от USL.
Независимо ни от чего мы пытались переписать Unix на языке более
высокого уровня, который развивался одновременно. Трудно сказать, что
чью эволюцию стимулировало, операционная система язык, или наоборот.
За полгода эти переписанные версии дважды пришлось переделывать, как
мне кажется, из-за проблем с языком. Пришлось внести в язык серьезные
изменения и переписать Unix.
Третья версия (я занимался основой ОС, ядром, а Деннис - блочным
вводом/выводом и диском) оказалась удачной; она и стала версией 5,
которая использовалась в лаборатории, а версия 6 была передана в
университеты. Затем была создана версия 7, где было сделано
перераспределение системы для подготовки первого переноса на Interdata
832, который осуществили Стив Джонсон и Деннис Ричи. Независимо от нас
аналогичный перенос был сделан в Австралии.
Что касается версии 6, агентство ARPA (Advanced Research Projects
Agency) приняло ее в качестве стандарта для сообщества Arpanet.
Университет Беркли получил контракт на поддержку и распространение
этой системы. Их основной вклад состоял в адаптации стека TCP/IP,
разработанного в Университете штата Иллинойс и добавлении виртуальной
памяти к версии, которую Bell Labs переносила на VAX.
|