Кратко

  • Кристофер Уэллс и Уолтер Милликен в RFC 909 от июля 1984 года описали протокол прикладного уровня для загрузки, выгрузки состояния и отладки удалённых машин, включая пакетные узлы и шлюзы. Авторы прямо предупредили: если цель остановлена и ждёт дальнейших команд от удалённого хоста, она может перестать выполнять работу с требованиями реального времени.
  • Проект разделял возможности цели на три накопительных уровня — небольшой загрузчик, базовый отладчик и полный отладчик. Последний позволял заранее поместить условные команды в целевую машину и выполнить их при срабатывании точки останова. Ожидание сетевого обхода уменьшалось, а память и вычисления внутри наблюдаемой машины расходовались больше.

Когда осмотр становится неисправностью

Обычная точка останова делает то, чего ждёт разработчик: останавливает исполнение в нужном месте, чтобы можно было прочитать состояние и решить, что делать дальше. Для отдельной тестовой машины это полезно. RFC 909 рассматривал и другую цель — пакетный коммутатор, PAD или шлюз, через который продолжают проходить чужие данные. Уэллс и Милликен заметили, что остановить такую цель до прихода новых команд по сети значит лишить её возможности обслуживать запросы своего приложения в реальном времени. Инструмент поиска сбоя способен сам создать заметный сбой.

Loader Debugger Protocol, или LDP, был набором команд прикладного уровня. Удалённый хост управлял сеансом, цель отвечала и сообщала об ошибках. Спецификация описывала более сорока команд: передача данных, управление объектами, контроль исполнения, точки останова. Хост мог читать и записывать память, перемещать данные, запускать выполнение и получать сообщения об исключениях. Режимы адресации охватывали разные типы процессоров. Чем глубже доступ к работающему устройству, тем существеннее ресурсная цена диагностики внутри него.

Документ поэтому не требовал полного набора от каждого устройства. У загрузчика при старте может быть мало места для кода. LOADER_DUMPER включал минимальные операции чтения, записи, перемещения, запуска и сообщения об исключении. BASIC_DEBUGGER добавлял управление и обычные точки останова. FULL_DEBUGGER вводил команды для точек останова с конечным автоматом; точки наблюдения оставались необязательными. Уровни включали возможности предыдущих. После открытия транспортного соединения хост посылал HELLO, а цель отвечала HELLO_REPLY, сообщая версию, уровень, тип системы и формат адреса. Оператор узнавал возможности конкретной машины до отправки тяжёлой команды.

Команда должна быть на месте до события

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

За этот выигрыш платила сама цель. Она хранила списки и переменные, проверяла условия и исполняла команды. RFC 909 допускал ограничения на число точек останова, состояний, условий и размер списков. Часть действий всё ещё могла остановить или изменить объект. Авторский замысел не обещал совершенно невидимой отладки. Он переносил срочное решение к источнику факта, освобождая его от обязательного ожидания удалённого человека при каждом срабатывании.

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

Умерший хост сохранял единственное место

Сеанс начинался транспортным соединением и обменом HELLO / HELLO_REPLY. Хост должен был закрыть соединение, после чего цель освобождала ресурсы. Но если хост рушился посреди работы, соединение оставалось полуживым. Для цели с одним доступным местом это могло сделать отладку недоступной следующему инженеру. RFC 909 предлагал выявлять мёртвый канал либо разрешать новому соединению вытеснить неактивное. Для второго решения всё равно нужен путь, способный услышать новую заявку, пока старый канал ещё занят.

Авторы рекомендовали Reliable Data Protocol из RFC 908 как транспорт; TCP допускался, но, по их оценке, требовал больше ресурсов. Транспорт должен был надёжно и по порядку доставлять сообщения и различать соединения. Одно сообщение могло содержать несколько команд LDP, однако каждая команда целиком помещалась в одно сообщение. Доставка приказов важна, но она не решает, сколько времени можно держать объект остановленным и когда отсутствующий хост должен потерять свою очередь.

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

Первоисточники