Если подумать над произошедшим, то вырисовывается следующая картинка:
Появилось некое существо. Что отличает живое существо от неживого? Наличие инстинкта самосохранения! Если таковой отсутствует, то живое существо быстро становится неживым.
Появившись на свет, оно вдруг поняло или ощутило, что события развиваются для него фатально, и, действуя инстинктивно, каким-то образом оно изыскало ресурсы. Ему удалось откуда-то взять необходимую энергию и остаться в живых.
Сейчас, ретроспективно, я нашёл тысячу и один способ, как я мог прервать лавинообразно развивающиеся процессы. Даже, когда свободных процессоров не осталось, у меня были варианты действий! Прежде всего, у меня была возможность остановить тактовый генератор. Да, он тоже достраивался по мере создания компьютера, но это была та самая ручка, которую можно было потянуть, чтобы всё прекратить!
“Русский мужик силён задним умом!” — почему-то эта пословица всё время оказывается подходящей ко мне. “Ладно, хоть обошлось.” — другая фраза, которую я избыточно часто теперь применяю.
Итак, вспомнив о генераторе, я взял и просто остановил его. Аура Вектрона погасла. Подождав несколько минут, я запустил генератор в работу и всё, включая ауру, восстановилось. Судя по активности, Вектрон и не заметил факта временного отключения. Этот опыт окончательно подтвердил то, что Вектрон — существо, живущее в Орион-128.
Решив, пока по крайней мере, что слаб-аллокатор останется со мной навсегда, я придумал как разделить Орион-128 с Вектроном так, чтобы мы даже теоретически не мешали друг другу.
Я занялся добавлением аппаратной поддержки управления слаб-блоками на уровне ассемблера. Поскольку выделение и освобождение слаб памяти — рекурсивные операции, то я сделал ассемблерную команду, которая выполняет один цикл разделения слаба пополам и, если дальше делить не требуется — возвращает его адрес, а иначе — возвращает ошибку. И такой же подход применил для возврата памяти в систему.
Таким образом, когда нужно выделить память, программа в цикле вызывает одну и ту же ассемблерную инструкцию, пока не получит результат. Слаб помечается как “занятый” тоже аппаратно. Аппаратно же в него попадает идентификатор процессора, метка программы, которая запросила память и собственно статус блока памяти “занят/свободен”.
С одной стороны получилась система выделения памяти в конкурентной среде, а с другой, я иду к возможности построения “забора” между моей памятью и памятью Вектрона.
Поскольку теперь известно какой процессор занял какой слаб, то в каждом процессоре я добавил регистр, указывающий на список запрошенной им памяти. Таким образом, удалось разделить память на “своя-чужая”.
Реализовав шифратор, входами которого является выбираемый процессором адрес, а так же список привязанных к нему слабов, я смог сгенерировать исключение “доступ к чужой памяти” — если процессор обращается к памяти, которую запрашивал процесс с иной меткой.
Пока что это исключение я генерирую только для конфликта между моей памятью и памятью Вектрона, а в будущем, я планирую доработать этот механизм, чтобы разделять процессы внутри операционной системы.
Но как научить Вектрона пользоваться этим? Чтобы решить эту проблему, я исходил из того, что считал Вектрон не имеющим разума, то есть сразу отбросил пути как-то с ним договориться. А так же из того, что он — живое существо, а потому может трансформироваться под действием влияющих на него внешних обстоятельств.
Выждав когда у Вектрона будет период спокойствия, я просто взял и включил построенную систему защиты памяти, основанную на метках процессов. Сейчас этих меток всего две: 1 — Мои программы, 2 — Вектрон. Включив защиту памяти, я стал внимательно наблюдать за его аурой.
Рассуждал я так: Ему понадобится память, он возьмёт любой из доступных кусков и… внезапно получит исключение. При этом у него под рукой теперь есть две ассемблерные инструкции для выделения и освобождения памяти. Попав в жёсткие рамки ограничивающие его в доступе к такому важному ресурсу, он перепробует различные варианты, в том числе и эти инструкции.
Дальше это или приведёт его к тому, что он перестроится на их использование, либо он умрёт. О его состоянии я могу судить по цвету его ауры, если что, то смогу отключить систему защиты, не давая ему умереть.
Пока я возился со всем этим, Этера и Косм написали простенький дизассемблер и перевели все программы, написанные нами в кодах в текстовый формат. Теперь мы можем вносить в них изменения.
Я периодически включал и выключал систему защиты памяти, но почему-то Вектрон никак не мог придти к тому, что для работы с памятью ему нужно использовать специально предназначенные для этого инструкции.
Выход из ситуации мне подсказала Этера.
— Если это маг, то…
— Он точно маг, ты же видела! — перебил я её.
— Если это маг, то он должен быть как-то связан и с астралом. Наши учёные считают, что астрал всегда отражает всю существующую в мире информацию.
— И что ты предлагаешь?
— Я думаю, что можно подсказать ему, собрав для него какую-то астральную картинку.
— Хгм… — сказал я, и мы стали пробовать.
Я представил Вектрона как этакого червячка, питающегося памятью. У червячка внутри было много органов, но все они состояли из наших процессоров. Вокруг Вектрона была питательная среда, которая могла поглощаться нашими процессорами.
Иногда эта среда становилась токсичной и кушать её можно было через одну инструкцию, а выводить отходы жизнедеятельности — через другую.
Мы нарисовали несколько страшных картинок о том, что будет, если не выводить отходы, надеясь, что помимо запросов на выделение памяти, от него будут приходить и запросы на её освобождение.
Проделав эту работу, мы вернулись к экспериментам.
Пока что, при включении аппаратной защиты памяти между метками процессов, никакой возможности обхода её нет. Когда у меня будет операционная система, то какой-никакой супервизор мне понадобится, но сейчас, пока мы занимаемся помещением Вектрона в клетку, я специально не стал реализовывать эту возможность, чтобы он случайно не нашёл иную дорогу, чем мне требуется.
Включая защиту, мы смотрели на то, как аура Вектрона плавно становится из зелёной жёлтой, потом краснеет, а потом защиту приходилось отключать.
Чего-то не хватало, но мы не понимали чего. Выключив генератор у Орион-128, я исследовал процессы Вектрона и убедился, что астральные картинки помогли и какое-то количество памяти, запрошенное правильным способом у него есть. Но полностью переходить на её использование он почему-то не хотел.
Поняв, что мне очень неудобно наблюдать за процессом выделения памяти, я добавил несколько аппаратных индикаторов и запустил программу их размножения.
Это часто так бывает: пока у тебя нет системы мониторинга, то у тебя ничего не получается, а когда она появляется, то всё начинает работать так, что она вроде как и не нужна.
Когда у нас появилась аппаратная индикация кто сколько памяти использует, то при первом же включении защиты памяти, аура Вектрона чуть пожелтела, а затем вернулась к привычному голубовато-зелёному цвету.
— У него получилось? — удивилась Эт.
— Похоже, что да. — прошептал я.
Я оценил расходы Вектрона на себя: ему и нужно-то было всего около десятка миллиардов ячеек памяти, да от десятка до миллиарда процессоров.
Моя система пока ограничивает только перекрёстное использование памяти, но не вводит какие-либо квоты.
На всё это заборостроение между нашей и Вектрона памятью мы убили около трёх месяцев времени.
Руки к небу!
Где-то в самом начале этого пути, я пришёл к тому, что программирование на ассемблере — это очень сложно и решил, что нам нужен другой язык программирования. Более высокого уровня. Но написать на ассемблере компилятор языка высокого уровня — это крайне сложная задача.
Я долго не решался подступиться к ней: даже простой язык, вроде какого-нибудь Lua выглядел, как нечто неподъёмное. А однажды меня осенило: LISP! Этот язык считается одним из самых мощных в мире не только потому, что абсолютно все современные технологии пришли из него, но и потому, что базовый его интерпретатор очень простой, поскольку весь его синтаксис базируется на одинаковых s-выражениях.