stringtranslate.com

Классическое управление памятью Mac OS

Окно «Об этом компьютере» Mac OS 9.1, показывающее потребление памяти каждым открытым приложением и самим системным программным обеспечением.

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

Первоначальной проблемой для инженеров Macintosh было то, как оптимально использовать 128 КБ оперативной памяти , которой была оснащена машина, на компьютерном оборудовании на базе Motorola 68000 , которое не поддерживает виртуальную память . [1] Поскольку в то время машина могла одновременно запускать только одну прикладную программу и не было фиксированной вторичной памяти , инженеры реализовали простую схему, которая хорошо работала с этими конкретными ограничениями. Этот выбор конструкции не подходил для разработки машины, создавая различные трудности как для программистов, так и для пользователей.

Фрагментация

Основной заботой первоначальных инженеров, судя по всему, была фрагментация – то есть многократное выделение и освобождение памяти с помощью указателей , приводящее к образованию множества небольших изолированных областей памяти, которые невозможно использовать, поскольку они слишком малы, даже несмотря на то, что общий объем свободной памяти может быть достаточным для удовлетворения конкретного запроса на память. Чтобы решить эту проблему, инженеры Apple использовали концепцию перемещаемого дескриптора — ссылки на память, которая позволяла перемещать фактические данные, на которые ссылаются, не делая дескриптор недействительным. Схема Apple была проста: дескриптор представлял собой просто указатель на (неперемещаемую) таблицу дальнейших указателей, которые, в свою очередь, указывали на данные. [2] Если запрос памяти требовал сжатия памяти, это делалось и таблица, называемая главным блоком указателей, обновлялась. Сама машина реализовала в памяти две области, доступные для этой схемы — системную кучу (используемую для ОС) и кучу приложений. [3] Пока запускалось только одно приложение, система работала хорошо. Поскольку при выходе из приложения вся куча приложения растворялась, фрагментация была сведена к минимуму.

Система управления памятью имела слабые места; системная куча не была защищена от ошибочных приложений, как это было бы возможно, если бы архитектура системы поддерживала защиту памяти , и это часто было причиной системных проблем и сбоев. [4] Кроме того, подход, основанный на дескрипторах, также открыл источник ошибок программирования, когда указатели на данные в таких перемещаемых блоках не могли быть гарантированно оставаться действительными при вызовах, которые могли вызвать перемещение памяти. Это было настоящей проблемой почти для каждого существующего системного API . Из-за прозрачности системных структур данных в то время API мало что могли сделать для решения этой проблемы. Таким образом, на программисте лежала обязанность не создавать такие указатели или, по крайней мере, очень осторожно управлять ими, разыменовывая все дескрипторы после каждого такого вызова API. Поскольку многие программисты в целом не были знакомы с этим подходом, ранние программы Mac часто страдали от ошибок, возникающих из-за этого. [5]

Palm OS и 16-битная Windows используют аналогичную схему управления памятью, но версии Palm и Windows усложняют ошибку программиста. Например, в Mac OS, чтобы преобразовать дескриптор в указатель, программа просто удаляет ссылку на дескриптор напрямую, но если дескриптор не заблокирован, указатель может быстро стать недействительным. Вызовы блокировки и разблокировки дескрипторов не сбалансированы; десять вызовов HLockотменяются одним вызовом HUnlock. [6] В Palm OS и Windows дескрипторы имеют непрозрачный тип и должны быть разыменованы с помощью MemHandleLockPalm OS или Global/LocalLockWindows. Когда приложение Palm или Windows завершает работу с дескриптором, оно вызывает MemHandleUnlockили Global/LocalUnlock. Palm OS и Windows ведут подсчет блокировок; после трех вызовов MemHandleLockблок разблокируется только после трех вызовов MemHandleUnlock.

Решение проблемы вложенных блокировок и разблокировок может быть простым (хотя и утомительным) с использованием различных методов, но они ухудшают читаемость соответствующего блока кода и требуют осведомленности и дисциплины со стороны программиста.

Утечки памяти и устаревшие ссылки

Осведомленность и дисциплина также необходимы, чтобы избежать «утечек» памяти (невозможность освободить память в пределах выделенной области) и избежать ссылок на устаревшие дескрипторы после выпуска (что обычно приводило к серьезному сбою , что раздражает однозадачную систему, потенциально катастрофически, если запущены другие программы).

Переключатель

Ситуация ухудшилась с появлением Switcher , который позволял Mac с 512 КБ и более памяти запускать несколько приложений одновременно. [7] Это был необходимый шаг вперед для пользователей, которые сочли подход «по одному приложению за раз» очень ограниченным. Поскольку Apple теперь была привержена своей модели управления памятью, а также совместимости с существующими приложениями, она была вынуждена принять схему, в которой каждому приложению выделялась собственная куча из доступной оперативной памяти. Фактический объем оперативной памяти, выделенной для каждой кучи, устанавливался значением, закодированным в метаданных каждого приложения, установленным программистом. Иногда этого значения было недостаточно для определенных видов работ, поэтому настройку значения приходилось предоставлять пользователю, чтобы он мог настроить размер кучи в соответствии со своими требованиями. Хотя это популярно среди « опытных пользователей », такое раскрытие деталей технической реализации противоречило философии пользователей Mac. Помимо того, что пользователи подвергались эзотерическим техническим тонкостям, это было неэффективно, поскольку приложение должно было захватить всю выделенную ему оперативную память, даже если большая ее часть впоследствии оставалась неиспользованной. Другое приложение может испытывать нехватку памяти, но не сможет использовать свободную память, «принадлежащую» другому приложению. [3]

Хотя приложение не может с пользой использовать кучу другого приложения, оно, безусловно, может уничтожить ее, обычно путем непреднамеренной записи на бессмысленный адрес. Приложение, случайно воспринявшее фрагмент текста или изображения или неназначенное место как указатель, могло легко перезаписать код или данные других приложений или даже ОС, оставив «скрытников» даже после выхода из программы. Такие проблемы может быть чрезвычайно сложно проанализировать и исправить.

Switcher превратился в MultiFinder в Системе 4.2, который стал Менеджером процессов в Системе 7 , и к тому времени эта схема уже давно укоренилась. Apple предприняла некоторые попытки обойти очевидные ограничения — временная память была одной из тех, где приложение могло «одолжить» свободную оперативную память, находящуюся за пределами ее кучи, на короткие периоды времени, но это было непопулярно среди программистов, поэтому в большинстве случаев не могло решить проблемы. Надстройка Apple System 7 Tune-up добавила «минимальный» размер памяти и «предпочтительный» размер - если предпочтительный объем памяти был недоступен, программа могла запускаться в минимальном пространстве, возможно, с ограниченной функциональностью. Это было включено в стандартную ОС, начиная с системы 7.1, но все еще не решило основную проблему. [8]

Схемы виртуальной памяти , которые делали больше памяти доступной за счет подкачки неиспользуемых частей памяти на диск, были доступны сторонними утилитами, такими как Connectix Virtual, а затем Apple в System 7 . Это увеличило объем памяти Macintosh за счет снижения производительности, но не добавило защищенной памяти и не предотвратило сжатие кучи диспетчера памяти, которое могло бы сделать недействительными некоторые указатели.

32-битная чистая

Первоначально Macintosh имел 128 КБ ОЗУ с реальным пределом в 4 МБ, несмотря на то, что он был припаян. Этот предел был впервые достигнут с Macintosh Plus и его памятью, обновляемой пользователем. Эти первые несколько компьютеров Macintosh используют ЦП 68000 , 32-битный процессор, который имеет только 24 физических адресных строки. 24 строки позволяют процессору адресовать до 16 МБ памяти (2 24 байта), что в то время считалось достаточным объемом. Ограничение ОЗУ в конструкции Macintosh составляло 4 МБ ОЗУ и 4 МБ ПЗУ, а остальные 8 МБ были разделены между чипами SCC, IWM и VIA из-за структуры карты памяти. [9] [10] Это было исправлено путем изменения карты памяти в Macintosh II , позволяющей использовать до 8 МБ ОЗУ, путем сокращения адресов ПЗУ и ввода-вывода до 1 МБ каждый и выделения оставшихся 6 МБ адресов слотам NuBus . . Продукты Connectix MAXIMA, RAM Doubler и Virtual позволяли получать доступ и перераспределять адреса размером 6 МБ, выделенные для карт NuBus, в общей сложности до 14 МБ минус 1 МБ на каждый занятый слот. [11] [12]

Поскольку память была дефицитным ресурсом, авторы классической Mac OS решили воспользоваться неиспользуемым байтом в каждом адресе. Исходный диспетчер памяти (вплоть до появления системы 7) размещал флаги в старших 8 битах каждого 32-битного указателя и дескриптора . Каждый адрес содержал такие флаги, как «заблокировано», «очищается» или «ресурс», которые хранились в главной таблице указателей. При использовании в качестве фактического адреса эти флаги маскировались и игнорировались ЦП. [4]

Несмотря на хорошее использование очень ограниченного пространства оперативной памяти, такая конструкция вызвала проблемы, когда Apple представила Macintosh II, в котором использовался 32-битный процессор Motorola 68020 . У 68020 было 32 физические адресные строки, которые могли адресовать до 4 ГБ памяти. Флаги, которые диспетчер памяти хранил в старшем байте каждого указателя и дескриптора, теперь были значимыми и могли привести к ошибкам адресации.

На компьютерах Macintosh IIci и более поздних версиях HLock()другие API были переписаны для реализации блокировки дескрипторов способом, отличным от пометки старших битов дескрипторов. Но многие программисты приложений Macintosh и большая часть самого кода системного программного обеспечения Macintosh обращались к флагам напрямую, а не с помощью API-интерфейсов, таких как HLock(), которые были предоставлены для управления ими. Сделав это, они сделали свои приложения несовместимыми с истинной 32-битной адресацией, и это стало известно как не «32-битная чистота».

Чтобы остановить постоянные сбои системы, вызванные этой проблемой, Система 6 и более ранние версии, работающие на 68020 или 68030, переводили машину в 24-битный режим и распознавали и обращались только к первым 8 мегабайтам ОЗУ, что является очевидным недостатком в машины, аппаратное обеспечение которых было рассчитано на работу с оперативной памятью до 128 МБ, и в документации по продуктам которых рекламировалась эта возможность. В System 7 системное программное обеспечение Mac наконец стало 32-битным, но проблема грязных ПЗУ все еще оставалась. Проблема заключалась в том, что решение об использовании 24-битной или 32-битной адресации должно быть принято на очень ранней стадии процесса загрузки, когда процедуры ПЗУ инициализируют диспетчер памяти для настройки базовой среды Mac, в которую загружаются ПЗУ NuBus и драйверы дисков. и казнен. Старые ПЗУ не имели поддержки 32-битного диспетчера памяти, поэтому невозможно было загрузиться в 32-битном режиме. Удивительно, но первое решение этой проблемы было опубликовано компанией-разработчиком программного обеспечения Connectix , чье расширение System 6, OPTIMA, повторно инициализировало диспетчер памяти и повторяло ранние части процесса загрузки Mac, позволяя системе загружаться в 32-битном режиме и позволяя использование всей оперативной памяти машины. Позже в 1991 году OPTIMA превратилась в более знакомый продукт MODE32 для System 7. Позже в 1991 году Apple лицензировала программное обеспечение у Connectix и распространяла его бесплатно. Компьютеры Macintosh IIci , а затем и более поздние версии компьютеров Macintosh на базе Motorola имели 32-битные чистые ПЗУ.

Прошло немало времени, прежде чем приложения были обновлены для удаления всех 24-битных зависимостей, и System 7 предоставила возможность вернуться в 24-битный режим, если была обнаружена несовместимость приложений. [3] Ко времени перехода на PowerPC и систему 7.1.2 32-битная чистота была обязательной для создания собственных приложений, и даже более поздние компьютеры Mac на базе Motorola 68040 не могли поддерживать 24-битный режим. [6] [13]

Ориентация объекта

Появление объектно-ориентированных языков для программирования Mac — сначала Object Pascal , а затем C++ — также вызвало проблемы для принятой модели памяти. На первый взгляд казалось естественным, что объекты будут реализовываться с помощью дескрипторов, чтобы получить преимущество возможности перемещения. Эти языки, в том виде, в котором они были изначально разработаны, использовали указатели на объекты, что приводило к проблемам фрагментации. Решение, реализованное компиляторами THINK ( позже Symantec ) , заключалось в том, чтобы использовать дескрипторы внутри объектов, но использовать синтаксис указателей для доступа к ним. Поначалу это казалось хорошей идеей, но вскоре возникли серьезные проблемы, поскольку программисты не могли определить, имеют ли они дело с перемещаемым или фиксированным блоком, и поэтому не имели возможности узнать, брать на себя задачу блокировки объектов или нет. Излишне говорить, что это привело к огромному количеству ошибок и проблем в ранних реализациях объектов. Более поздние компиляторы не пытались сделать это, а использовали настоящие указатели, часто реализуя свои собственные схемы распределения памяти для обхода модели памяти Mac OS.

Хотя модель памяти Mac OS, со всеми присущими ей проблемами, оставалась неизменной вплоть до Mac OS 9 из-за серьезных ограничений совместимости приложений, растущая доступность дешевой оперативной памяти означала, что в целом большинство пользователей могли перейти на новую версию. угол. Память использовалась неэффективно, но ее было достаточно, чтобы проблема не стала критической. Это иронично, учитывая, что целью первоначального проекта было максимальное использование очень ограниченного объема памяти. Mac OS X наконец покончила со всей этой схемой, реализовав современную схему страничной виртуальной памяти . Подмножество API-интерфейсов старой модели памяти все еще существует для совместимости как часть Carbon , но сопоставляется с современным менеджером памяти (потокобезопасная mallocреализация) ниже. [6] Apple рекомендует использовать код Mac OS Xmalloc « freeпочти исключительно». [14]

Рекомендации

  1. ^ Херцфельд, Энди (сентябрь 1983 г.), Оригинальный Macintosh: мы не хакеры! , получено 10 мая 2010 г.
  2. Херцфельд, Энди (январь 1982 г.), The Original Macintosh: венгерский, заархивировано из оригинала 19 июня 2010 г. , получено 10 мая 2010 г.
  3. ^ abc Memorymanagement.org (15 декабря 2000 г.), Управление памятью в Mac OS, заархивировано из оригинала 16 мая 2010 г. , получено 10 мая 2010 г.
  4. ↑ Аб Херцфельд, Энди , The Original Macintosh: Mea Culpa , получено 10 мая 2010 г.
  5. ^ Apple Computer (1 октября 1985 г.), Техническое примечание OV09: Отладка с помощью PurgeMem и CompactMem , получено 10 мая 2010 г.
  6. ^ Справочник abc Legacy Memory Manager, Apple Inc. , 27 июня 2007 г. , получено 10 мая 2010 г.
  7. ^ Херцфельд, Энди (октябрь 1984 г.), The Original Macintosh: Switcher , получено 10 мая 2010 г.
  8. ^ «Руководство по обновлению системы 7.1» (PDF) . Архивировано из оригинала (PDF) 4 марта 2016 года . Проверено 26 мая 2015 г.
  9. ^ Переход с 24-битной на 32-битную адресацию — графический интерфейс Mac
  10. ^ «карты памяти». Осдата.com. 28 марта 2001 года . Проверено 11 мая 2010 г.
  11. ^ Архив Daystar, Часто задаваемые вопросы по Mode32 - LowEndMac
  12. ^ MODE32 Версия 7.5 — Важные примечания к выпуску и инструкции
  13. ^ Apple Computer (1 января 1991 г.), Техническое примечание ME13: Совместимость с диспетчером памяти , получено 10 мая 2010 г.
  14. ^ Рекомендации по распределению памяти в OS X, Apple Inc , 12 июля 2005 г. , получено 22 сентября 2009 г.

Внешние ссылки