Взаимно недоверяющие подсистемы
Но еше больше проблем создает операция уничтожения мандата. Легко показать необходимость уничтожения мандата той же задачей, которая его создала.
Например, представим себе, что пользовательская программа передала какому-либо модулю мандат на запись в динамически выделенный буфер. Допустим также, что этот модуль вместо уничтожения мандата после передачи данных сохранил его – ведь наша система предполагает, что ни одному из модулей нельзя полностью доверять! Если мы вынуждены принимать в расчет такую возможность, то не можем ни повторно использовать такой буфер для других целей, ни даже возвратить память, занятую им системе, потому что не пользующийся нашим доверием модуль по-прежнему может сохранять право записи в него.
В свете этого возможность для задачи, выдавшей мандат, в одностороннем порядке прекращать его действие представляется жизненно необходимой. Отказ от этой возможности или ее ограничение приводит к тому, что задача. выдающая мандат, вынуждена доверять тем задачам, которым мандат был передан, т. е. можно не городить огород и вернуться к обычной двухуровневой или многоуровневой системе колец защиты.
Для прекращения действия мандата мы должны отыскать в нашей общесистемной базе данных все ссылки на интересующий нас объект и объявить не недействительными. При этом мы должны принять во внимание возможности многократной передачи мандата и повторной выдачи мандатов на отдельные части объекта. Аналогичную задачу нужно решать при перемещении объектов в памяти во время дефрагментации, сбросе на диск и поиске жертвы (см. разд. "Поиск жертвы") для такого сброса.
Структура этой базы данных представляется нам совершенно непонятной, потому что она должна отвечать следующим требованиям.
- Обеспечивать быстрый поиск всех селекторов сегментов, ссылающихся на заданный байт или слово памяти.
- Обеспечивать быстрое и простое добавление новых селекторов, ссылающихся на произвольные части существующих сегментов.
- Занимать не больше места, чем память, отведенная под сегменты.
Последнее требование непосредственно не следует из концепции взаимно недоверяющих подсистем, но диктуется простым здравым смыслом. Если мы и смиримся с двух – или более кратным увеличением потребностей в памяти, оправдывая его повышением надежности, нельзя забывать, что даже простой просмотр многомегабайтовых таблиц не может быть быстрым.
В системах, использующих страничные диспетчеры памяти, решить эти Проблемы намного проще, потому что минимальным квантом разделения Памяти является страница размером несколько килобайтов. Благодаря этому Мы смело можем связать с каждым разделяемым квантом несколько десятков байтов данных, обеспечивающих выполнение первых двух требований.
Если же минимальным квантом является байт или слово памяти, наши структуры данных окажутся во много раз больше распределяемой памяти.
Автор оставляет читателю возможность попробовать самостоятельно разработать соответствующую структуру данных. В качестве более сложного упражнения можно рекомендовать записать алгоритм работы с такой базой данных на псевдокоде, учитывая, что мы хотели бы иметь возможность реализовать этот алгоритм аппаратно или, по крайней мере, микропрограммно.
Дополнительным стимулом для читателя, решившего взяться за эту задачу, может служить тот факт, что разработчики фирмы Intel не смогли найти удовлетворительного решения.
Архитектура 1432
Автору известен только один процессор, пригодный для полноценной реализации взаимно недоверяющих подсистем: JAPX432 фирмы Intel. Вместо создания системной базы данных о множественных ссылках на объекты, специалисты фирмы Intel усложнили диспетчер памяти и соответственно алгоритм разрешения виртуальных адресов.
Виртуальный адрес в 1432 состоит из селектора объекта и смещения в этом объекте. Селектор объекта ссылается на таблицу доступа текущего домена. Домен представляет собой программный модуль вместе со всеми его статическими и динамическими данными (рис. 5.12). По идее разработчиков, домен соответствует замкнутому модулю языков высокого уровня, например пакету (package) языка Ada.
Рис. 5.12. Домен 1432