VII
VII
Похоже, Ари Лемке страдал излишним оптимизмом. Он создал каталог (ftp.funet.fi) задолго до того, как у меня появилось что туда положить. У меня был пароль, и все было готово для того, чтобы я мог просто войти в систему и закачать свою программу. Но прошло долгих четыре месяца, прежде чем мне захотелось чем-нибудь поделиться с миром или хотя бы с Ари и несколькими другими фанатами операционных систем, с которыми я переписывался.
Исходно я хотел написать такую операционку, которую мог бы использовать вместо Minix. Мне не нужно было, чтобы она могла делать больше, чем Minix, но она должна была выполнять те функции Minix, которыми я пользовался, а также кое-что еще. Например, в Minix не только была плохая эмуляция терминала, но и не было возможности перевести в фоновый режим программу, которой временно не пользуешься. И управление памятью было очень упрощенным – в Mac OS оно и сейчас такое, кстати.
Как создать операционку? Надо выяснить, что должны делать системные вызовы, и написать программы, которые будут это делать. Вообще говоря, системных вызовов около двух сотен. Некоторые из них могут соответствовать целому набору функций. Другие – совсем просты. Наиболее фундаментальные системные вызовы могут быть весьма сложными и в значительной мере зависят от имеющейся инфраструктуры. Возьмем системные вызовы Write (запись) и Read (чтение). Для записи на диск и чтения с диска нужно создать драйвер дисковода. Возьмем вызов Open (открыть). Нужно создать весь уровень файловой системы, который будет анализировать имена и определять, где что лежит на диске. На один этот системный вызов ушло несколько месяцев. Но когда он был уже готов, тот же самый программный код можно было использовать и для других функций.
Так шла разработка на ранних этапах. Я читал стандарты в руководствах к Sun OS и других книжках, брал системные вызовы один за другим и старался написать что-нибудь работающее. Это было довольно изнурительно.
А все потому, что, когда ничего не происходит, трудно оценить объем сделанного. Можно писать маленькие тестики, которые будут проверять то, что ты только что добавил. Но при этом реально ничего не выполняется. Через некоторое время я бросил перебирать системные вызовы по списку и перешел к другому методу. Получилась довольно полная система, и мне захотелось выполнить настоящую программу. Первым делом нужно запустить оболочку, потому что без нее довольно трудно запустить что-нибудь еще. А кроме того, оболочка сама по себе содержит множество системных вызовов, которые все равно понадобятся. Стоит ее запустить, и можно получить текущий список системных вызовов, которые еще не реализованы.
В Unix оболочка – это своего рода мать всех программ. Она всегда наготове, чтобы запустить любой другой бинарник. (Бинарник – это программа, составленная из нулей и единиц – на языке, который понимает машина. Если вы написали программу на каком-то языке программирования, нужно откомпилировать исходный код, чтобы получить бинарник.) Прежде всего оболочка позволяет вам войти в систему. Ну хорошо, в реальной Unix-системе по традиции первая программа, которую вы запускаете, это init, но для работы init необходима большая инфраструктура. Это своего рода контроллер происходящего. Но если у вас нет ничего работающего, то вам и init не нужна.
Поэтому мое ядро запускало не init, а оболочку. К тому времени я реализовал около двадцати пяти системных вызовов и, как я уже писал, это была первая настоящая программа, которую я хотел запустить. Оболочку я сам не писал. Я загрузил к себе на диск клон Bourne Shell, одной из исходных оболочек Unix. Он бесплатно распространялся по Интернету, и его название представляло собой плохой каламбур. Исходную оболочку написал чувак по имени Bourne, поэтому клон назывался Bourne-Again Shell[7]. Обычно его сокращали до bash.
Стоит начать загружать с диска настоящую программу, как обнаруживается прокол в драйвере дисковода или в загрузчике, так что тот не понимает, что считывает. Поэтому он выдает комментарии по ходу своих действий. Это очень важно, потому что только так можно узнать, в чем беда.
Я дошел до той стадии, когда моя программа загружала оболочку и выдавала на печать сообщение о каждом системном вызове, который содержался в оболочке, но который я еще не реализовал. Я загружался, запускал оболочку, а она выплевывала что-нибудь типа: «Системный вызов 512 не выполнен». День и ночь я вчитывался в распечатки системных вызовов, пытаясь понять, какие я написал неправильно. Но это было намного увлекательнее, чем идти по списку системных вызовов и реализовывать их один за другим. Теперь продвижение было более наглядным.
Наконец, в конце августа или начале сентября, оболочка заработала. После этого все стало намного проще.
Это был важный момент.
Как только оболочка заработала, я почти сразу же смог откомпилировать еще несколько программ. Оболочка была сложнее, чем, к примеру, программа копирования cp или команда выдачи листинга каталогов ls. Все нужное уже было сделано для оболочки, поэтому, когда она заработала, произошел резкий скачок от практически нулевой отметки до ста, ведь все составные части уже были на месте. В какой-то момент готовых компонент оказалось столько, что настал миг типа «Да будет свет!», потому что до этого ничего по-настоящему не работало.
Я был страшно доволен. Особенно потому, наверное, что в то лето ничем, кроме программирования, не занимался. И это не преувеличение. С апреля по август в Финляндии лучше всего. Все плавают на лодках между островами, загорают на пляжах, сидят в дачных саунах. Я же редко вообще знал, день сейчас или ночь, рабочий день или выходной. Плотные черные занавески отгораживали меня от почти круглосуточного солнечного света и вообще от внешнего мира. В иные дни (или ночи?) я выпрыгивал прямо из постели на стул перед компьютером, до которого было примерно полметра. Мой отец, по-видимому, уговаривал маму заставить меня наняться на лето на работу. Но ей было все равно: я ей не мешал. Вот Сара немного сердилась, что занят телефон, когда я выходил в онлайн. (Она бы, вероятно, выразила эту мысль несколько менее дипломатично.) Без всякого преувеличения можно сказать, что у меня практически не было контактов с миром вне моего компьютера. Ну хорошо, может, раз в неделю в окно стучал приятель, и если я не просматривал в это время на экране какую-нибудь важную программу, то впускал его в дом. (Это всегда был «он» – вы помните, это было еще до того, как хакеры стали популярны среди девушек.) Мы садились на часок попить чаю и посмотреть MTV в нашей кухоньке. Теперь, когда я задумался, то начинаю припоминать, что иногда выходил выпить пива или сыграть в снукер, если в окно стучался кто-нибудь вроде Иоуко (я обычно зову его «Авутоном»). Но больше, честное слово, в моей жизни ничего в то время не происходило.
И я ни в малейшей степени не чувствовал себя жалким бледным яйцеголовым неудачником. Оболочка работала, а это значило, что я фактически построил основу работоспособной операционной системы. И я получал удовольствие.
Когда оболочка заработала, я стал тестировать встроенные в нее программы. Потом я накомпилировал достаточно новых программ, чтобы начать делать что-то настоящее. Я компилировал все в Minix, но перенес оболочку в специальный раздел, который создал для новой операционной системы. Про себя я называл ее Linux.
Честное слово, я никогда не собирался выпускать ее под именем Linux, потому что это казалось мне слишком нескромным. Какое имя я приготовил для окончательной версии? Freax. (Поняли? Freaks – фанаты – и на конце x от Unix.) На самом деле некоторые ранние файлы проекта – файлы, где описывается, как компилировать исходники – около полугода содержали название Freax. Но это не имело особого значения. В то время мне не нужно было название, потому что я не собирался ее никому показывать.