Сейбел: Был ли в систему встроен отладочный код?

Козелл: Нет.

Сейбел: Значит, с каждым сложным багом приходилось возиться отдельно?

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

Но тогда мы даже не думали об этом. Мы просто старались написать эту чрезвычайно сложную систему реального времени так, чтобы она работала быстро. Это само по себе было трудной задачей. Мы не закладывали никаких проверок на непротиворечивость; к чему тратить на это время? Так что все исправления вносились потом бессистемно. Загляни в такой-то раздел памяти, просмотри код, чтобы разобраться с тем, или другим, или третьим, потом вернись и начни сначала.

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

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

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

Сейбел: Это были буквально ряды лампочек?

Козелл: Да, ряды лампочек. Одна лампочка - один бит.

Сейбел: И тумблеры для ввода адресов?

Козелл: Да. Я считаю, это лучше. На PDP-1 были тумблеры. На той машине, о которой мы говорим сейчас, помнится, были кнопки.

Сейбел: Как вам троим работалось вместе?

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

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

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

И вот я думал: какими базовыми константами пользовался Уилл, собирая все это вместе? Когда два тайм-аута были одинаковыми по длине, было ли это совпадением или то был один и тот же тайм-аут? Кто знает? Сколько нужно внести изменений в код, чтобы изменить одну константу? Если в процессе работы замечаешь, что ждешь чего-то недостаточно долго и операция завершается по тайм-ауту, когда не должна, то понимаешь, что не можешь просто взять и изменить один тайм-аут в программе, потому что там все взаимосвязано.

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

Сейбел: Таким образом вы исправляли ошибки или просто подводили под работу системы более прочную базу, чтобы в будущем не нужно было возвращаться к одному и тому же?

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

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

Он был не настолько хорош, чтобы выдавать на 100% идеальный готовый код. Но его код был на 75- 80% вполне приличным и в большинстве случаев работал. Когда он ушел в другой проект - TIP, если не ошибаюсь, - мы с Дэйвом продолжали работать над системой IMP, и именно тогда я переписал алгоритм маршрутизации, поскольку не понимал, откуда взялись заложенные в нем константы. Это по-прежнему оставался алгоритм Уилла, но переписанный в моем стиле. И теперь я понимал, как и почему он работает, потому что сам заставил его работать.

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

Сейбел: Итак, у вас был листинг оригинального исходника, который нужно было скормить ассемблеру...

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

Сейбел: Значит, перфолента содержала двоичную версию заплатки?

Козелл: Да. Потом уже я написал маленький интерактивный отладчик, выполнявший функции проверки и помещения заплатки в нужное место. Это существенно облегчало работу: можно было нанести на ленту такую программу: “Перейти по адресу 12785, значение, значение, значение, значение. Пустая строка. Перейти по адресу 12832, значение, значение, значение, значение, значение”. Если надо было загрузить программу с нуля, то сначала загружалась сама программа, потом - лента с заплатками.

Сейбел: Значит, на том этапе у вас не было никакого исходного кода, который

Добавить отзыв
ВСЕ ОТЗЫВЫ О КНИГЕ В ИЗБРАННОЕ

0

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

Отметить Добавить цитату