Управление памятью в MacOS и Win16

В этих системах предполагается, что пользовательские программы не сохра­няют указателей на динамически выделенные блоки памяти. Вместо этого каждый такой блок идентифицируется целочисленным дескриптором или "ручкой" (handle). Когда программа непосредственно обращается к данным в блоке, она выполняет системный вызов GiobaiLock (запереть). Этот вызов возвращает текущий адрес блока. Пока программа не исполнит вызов Giobaiuniock (отпереть), система не пытается изменить адрес блока. Если же блок не заперт, система считает себя вправе передвигать его по па­мяти или даже сбрасывать на диск.

"Ручки" представляют собой попытку создать программный аналог аппарат­ных диспетчеров памяти. Они позволяют решить проблему фрагментации и даже организовать некое подобие виртуальной памяти. Можно рассматри­вать их как средство организации оверлейных данных - поочередного ото­бражения разных блоков данных на одни и те же адреса. Однако за это приходится платить очень дорогой ценой.

Использование "ручек" сильно усложняет программирование вообще и в особенности перенос ПО из систем, использующих линейное адресное пространство. Все указатели на динамические структуры данных в программе нужно заменить на "ручки", а каждое обращение к таким структурам необходимо окружить вызовами GlobalLock/GlobalUnlock.

 

Вызовы GlobalLock/GlobalUnlock:

□ сами по себе увеличивают объем кода и время исполнения;

□ мешают компиляторам выполнять оптимизацию, прежде всего не позво­ляют оптимально использовать регистры процессора, потому что далеко не все регистры сохраняются при вызовах; □ требуют разрыва конвейера команд и перезагрузки командного кэша; в современных суперскалярных процессорах это может приводить к па­дению производительности во много раз.

 

Попытки уменьшить число блокировок требуют определенных интеллекту­альных усилий. Фактически, к обычному циклу разработки ПО: проектирование, выбор алгоритма, написание кода и его отладка — добавляются еще две фазы: микрооптимизация использования "ручек" и отладка оптимизированного кода. Последняя фаза оказывается, пожалуй, самой сложной и ответственной.

Наиболее опасной ошибкой, возникающей на фазе микрооптимизации, является вынос указателя на динамическую структуру за пределы скобок GiobaiLock/Giobaiumock. Эту ошибку очень сложно обнаружить при тестировании, так как она проявляется, только если система пыталась передвигать блоки в промежутках между обращениями. Иными словами, ошибка может проявлять или не проявлять себя в зависимости от набора приложений, исполняющихся в системе, и от характера деятельности этих приложений. В результате мы получаем то, чего больше всего боятся эксплуатационники - систему, которая работа иногда. При переходе от Windows 3.x к Windows 95 наработка на отказ - даже при исполнении той же самой смеси приложении – резко возросла, так что система из работающей иногда превратилась в работающую, как правило. По-видимому, это означает, что большая часть ошибок в приложениях Win16 действительно относилась к ошибкам работы с "ручками".

Не случайно фирма Microsoft полностью отказалась от управления памятью помощью "ручек" в следующей версии MS Windows — Windows 95, в которой реализована почти полноценная виртуальная память.

Mac OS версии 10, построенная на ядре BSD Unix, также имеет страничную виртуальную память и никогда не перемещает блоки памяти, адресуемые «ручками».