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

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

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

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

Содержание

  • 1 Фрагментация
  • 2 Утечки памяти и устаревшие ссылки
  • 3 Switcher
  • 4 32-битная очистка
  • 5 Ориентация объекта
  • 6 Ссылки
  • 7 Внешние ссылки

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

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

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

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

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

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

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

Switcher

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

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

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

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

32-битный чистый

Изначально Macintosh имел 128 КБ ОЗУ с ограничением 512 КБ. После появления Macintosh Plus он был увеличен до 4 МБ. Эти компьютеры Macintosh использовали ЦП 68000, 32-разрядный процессор, но имели только 24 строки физического адреса. 24 строки позволяли процессору адресовать до 16 МБ памяти (2 байта), что в то время считалось достаточным объемом. Предел ОЗУ в конструкции Macintosh составлял 4 МБ ОЗУ и 4 МБ ПЗУ из-за структуры карты памяти. Это было исправлено путем изменения карты памяти в Macintosh II и Macintosh Portable, что позволило использовать до 8 МБ ОЗУ.

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

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

Теоретически разработчики системного программного обеспечения Macintosh могли свободно изменять схему «флаги в старшем байте», чтобы избежать этой проблемы, и они это сделали. Например, на компьютерах 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, чей продукт MODE32 1991 года повторно инициализировал диспетчер памяти и повторил ранние части процесса загрузки Mac, что позволило системе загрузиться в 32-битном режиме и задействовать всю оперативную память машины. Apple лицензировала программное обеспечение Connectix позже в 1991 году и распространяла его бесплатно. Компьютеры Macintosh на базе Macintosh IIci и более поздних версий Motorola имели 32-разрядные чистые ПЗУ.

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

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

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

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

Ссылки

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

Последняя правка сделана 2021-05-15 10:16:57
Содержание доступно по лицензии CC BY-SA 3.0 (если не указано иное).
Обратная связь: support@alphapedia.ru
Соглашение
О проекте