stringtranslate.com

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

Управление памятью — это форма управления ресурсами , применяемая к памяти компьютера . Основным требованием к управлению памятью является предоставление способов динамического выделения частей памяти программам по их запросу и освобождения ее для повторного использования, когда она больше не нужна. Это критически важно для любой продвинутой компьютерной системы, в которой в любой момент времени может выполняться более одного процесса . [1]

Было разработано несколько методов, повышающих эффективность управления памятью. Системы виртуальной памяти отделяют адреса памяти , используемые процессом, от реальных физических адресов, позволяя разделить процессы и увеличить размер виртуального адресного пространства сверх доступного объема ОЗУ с помощью подкачки или переключения на вторичное хранилище . Качество диспетчера виртуальной памяти может оказать существенное влияние на общую производительность системы .

В некоторых операционных системах , например OS/360 и последующих версиях , [2] памятью управляет операционная система. [примечание 1] В других операционных системах, например Unix-подобных операционных системах, управление памятью осуществляется на уровне приложения.

Управление памятью в адресном пространстве обычно подразделяется на ручное или автоматическое управление памятью.

Ручное управление памятью

Пример внешней фрагментации

Задача выполнения запроса на выделение состоит в поиске блока неиспользуемой памяти достаточного размера. Запросы на память удовлетворяются путем выделения частей из большого пула [примечание 2] памяти, называемого кучей [примечание 3] или свободным хранилищем . В любой момент времени некоторые части кучи используются, а некоторые «свободны» (не используются) и, следовательно, доступны для будущего распределения. В языке C вызывается функция, которая выделяет память из кучи, mallocа также функция, которая берет ранее выделенную память и помечает ее как «свободную» (для использования при будущих выделениях) free. [примечание 4]

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

Эффективность

Реализованный конкретный алгоритм динамического выделения памяти может существенно повлиять на производительность. Исследование, проведенное в 1994 году Digital Equipment Corporation, иллюстрирует накладные расходы , связанные с различными распределительами. Наименьшая средняя длина пути команд , необходимая для выделения одного слота памяти, составляла 52 (согласно измерениям с помощью профилировщика уровня инструкций в различных программах). [1]

Реализации

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

Распределение блоков фиксированного размера

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

Блоки друзей

В этой системе память распределяется по нескольким пулам памяти, а не только по одному, где каждый пул представляет собой блоки памяти определенной степени двойки по размеру или блоки какой-либо другой удобной прогрессии размера. Все блоки определенного размера хранятся в отсортированном связанном списке или дереве , а все новые блоки, образующиеся во время выделения, добавляются в соответствующие пулы памяти для дальнейшего использования. Если запрашивается меньший размер, чем доступен, выбирается наименьший доступный размер и разделяется. Выбирается одна из получившихся частей, и процесс повторяется до тех пор, пока запрос не будет завершен. Когда блок выделяется, распределитель начинает с наименьшего достаточно большого блока, чтобы избежать ненужного разрушения блоков. Когда блок освобождается, он сравнивается со своим партнером. Если они оба свободны, они объединяются и помещаются в список блоков друзей соответствующего большего размера.

Распределение плит

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

Распределение стека

Многие Unix-подобные системы, а также Microsoft Windows реализуют функцию, предназначенную allocaдля динамического выделения памяти стека, аналогично malloc. Компилятор обычно преобразует его во встроенные инструкции, манипулирующие указателем стека. [5] Хотя нет необходимости вручную освобождать память, выделенную таким образом, поскольку она освобождается автоматически, когда вызвавшая функция allocaзавершает работу, существует риск переполнения. А поскольку alloca — это специальное расширение, которое встречается во многих системах, но никогда не встречается в POSIX или стандарте C, его поведение в случае переполнения стека не определено.

В Microsoft Windows существует более безопасная версия alloca _malloca, которая сообщает об ошибках. Это требует использования _freea. [6] gnulib предоставляет эквивалентный интерфейс, хотя вместо выдачи исключения SEH при переполнении он делегирует функции malloc при обнаружении слишком большого размера. [7] Подобную функцию можно эмулировать с помощью ручного учета и проверки размера, например, при использовании alloca_accountв glibc. [8]

Автоматизированное управление памятью

Правильное управление памятью в приложении является сложной проблемой, и было разработано несколько различных стратегий управления памятью.

Автоматическое управление переменными стека вызовов

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

Вывоз мусора

Сбор мусора — это стратегия автоматического обнаружения памяти, выделенной для объектов, которые больше не могут использоваться в программе, и возврата этой выделенной памяти в пул свободных ячеек памяти. Этот метод отличается от «ручного» управления памятью, когда программист явно кодирует запросы и освобождения памяти в программе. Хотя автоматическая сборка мусора имеет преимущества, заключающиеся в уменьшении рабочей нагрузки программиста и предотвращении определенных видов ошибок распределения памяти, сборка мусора требует собственных ресурсов памяти и может конкурировать с прикладной программой за процессорное время.

Подсчет ссылок

Подсчет ссылок — это стратегия обнаружения того, что память больше не может использоваться программой, путем поддержания счетчика количества независимых указателей, указывающих на память. Всякий раз, когда новый указатель указывает на участок памяти, программист должен увеличить счетчик. Когда указатель меняет то место, куда он указывает, или когда указатель больше ни на что не указывает или сам был освобожден, счетчик должен уменьшиться. Когда счетчик упадет до нуля, память следует считать неиспользуемой и освобожденной. Некоторые системы подсчета ссылок требуют участия программиста, а некоторые реализуются автоматически компилятором. Недостаток подсчета ссылок заключается в том, что могут возникать циклические ссылки, вызывающие утечку памяти. Это можно смягчить, добавив концепцию «слабой ссылки» (ссылка, которая не участвует в подсчете ссылок, но получает уведомление, когда объект, на который она указывает, больше не действителен) или путем объединения подсчета ссылок и сборки мусора. .

Пулы памяти

Пул памяти — это метод автоматического освобождения памяти в зависимости от состояния приложения, например жизненного цикла запроса или транзакции. Идея состоит в том, что многие приложения выполняют большие фрагменты кода, которые могут генерировать выделение памяти, но в какой-то момент выполнения все эти фрагменты становятся недействительными. Например, в веб-службе после каждого запроса веб-служба больше не нуждается в памяти, выделенной во время выполнения запроса. Таким образом, вместо отслеживания того, используется ли память в данный момент или нет, память выделяется в соответствии с запросом или этапом жизненного цикла, с которым она связана. Когда этот запрос или этап пройден, вся связанная память освобождается одновременно.

Системы с виртуальной памятью

Виртуальная память — это метод отделения организации памяти от физического оборудования. Приложения работают с памятью через виртуальные адреса . Каждая попытка приложения получить доступ к определенному адресу виртуальной памяти приводит к преобразованию адреса виртуальной памяти в реальный физический адрес . [9] Таким образом, добавление виртуальной памяти обеспечивает детальный контроль над системами памяти и методами доступа.

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

Несмотря на то, что память, выделенная для определенных процессов, обычно изолирована, иногда процессам требуется возможность совместного использования информации. Общая память — один из самых быстрых методов межпроцессного взаимодействия .

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

Управление памятью в OS/360 и последующих версиях

IBM System/360 не поддерживает виртуальную память. [примечание 5] Изоляция памяти заданий дополнительно осуществляется с помощью ключей защиты , при этом каждому заданию назначается отдельный ключ хранилища: 0 для супервизора или 1–15. Управление памятью в OS/360 является функцией супервизора . Память запрашивается с помощью GETMAINмакроса и освобождается с помощью FREEMAINмакроса, что приводит к вызову супервизора ( SVC ) для выполнения операции.

В OS/360 детали различаются в зависимости от того, как сгенерирована система , например, для PCP , MFT , MVT .

В OS/360 MVT перераспределение внутри региона задания или общей системной области очереди (SQA) основано на подпулах — областях, размер которых кратен 2 КБ — размер области, защищенной ключом защиты. Подпулы имеют номера 0–255. [10] Внутри региона подпулам назначается либо защита хранилища задания, либо ключ супервизора, ключ 0. Подпулы 0–127 получают ключ задания. Первоначально создается только нулевой подпул, и все пользовательские запросы к памяти удовлетворяются из подпула 0, если в запросе памяти не указано иное. Подпулы 250–255 создаются супервизором по запросам памяти от имени задания. Большинству из них присвоен ключ 0, хотя некоторые получают ключ задания. Номера подпулов также актуальны в MFT, хотя детали гораздо проще. [11] MFT использует фиксированные разделы , переопределяемые оператором, вместо динамических регионов, а PCP имеет только один раздел.

Каждый подпул отображается списком блоков управления, определяющих выделенные и свободные блоки памяти внутри подпула. Память выделяется путем поиска свободной области достаточного размера или путем выделения дополнительных блоков в подпуле до размера региона задания. Можно освободить всю или часть выделенной области памяти. [12]

Детали для OS/VS1 аналогичны [13] деталям для MFT и MVT; Детали для OS/VS2 аналогичны данным для MVT, за исключением того, что размер страницы составляет 4 КиБ. Как для OS/VS1, так и для OS/VS2 общая область системной очереди (SQA) не поддается выгрузке.

В MVS адресное пространство включает в себя дополнительную общую область с возможностью выдачи страниц, общую область хранения (CSA), и дополнительную частную область, рабочую область системы (SWA). Кроме того, все ключи хранения 0–7 зарезервированы для использования привилегированным кодом.

Смотрите также

Примечания

  1. ^ Однако среда выполнения языкового процессора может разделять память, динамически полученную от операционной системы, например, для реализации стека.
  2. ^ В некоторых операционных системах, например OS/360 , свободное хранилище может быть разделено различными способами, например, на подпулы в OS/360 , под чертой, над чертой и над чертой в z/OS .
  3. ^ Не путать с несвязанной структурой данных кучи .
  4. ^ Упрощенную реализацию этих двух функций можно найти в статье «Управление внутренней памятью». [3]
  5. ^ За исключением модели 67.

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

  1. ^ аб Детлефс, Д.; Доссер, А.; Зорн, Б. (июнь 1994 г.). «Затраты на выделение памяти в больших программах на C и C++» (PDF) . Программное обеспечение: практика и опыт . 24 (6): 527–542. CiteSeerX  10.1.1.30.3073 . дои : 10.1002/спе.4380240602. S2CID  14214110.
  2. ^ «Распределение основной памяти» (PDF) . Концепции и возможности операционной системы IBM/360 (PDF) . Справочная библиотека систем IBM (первое издание). Корпорация IBM. 1965. с. 74 . Проверено 3 апреля 2019 г.
  3. ^ Джонатан Бартлетт. «Управление внутренней памятью». IBM DeveloperWorks .
  4. ^ Зильбершац, Авраам ; Гэлвин, Питер Б. (2004). Концепции операционной системы . Уайли. ISBN 0-471-69466-5.
  5. ^ alloca(3)  -  Руководство программиста Linux - Библиотечные функции
  6. ^ "_malloca". Документация Microsoft CRT .
  7. ^ "gnulib/malloca.h". Гитхаб . Проверено 24 ноября 2019 г.
  8. ^ "glibc/include/alloca.h". Зеркала Берена Минора. 23 ноября 2019 г.
  9. ^ Таненбаум, Эндрю С. (1992). Современные операционные системы . Энглвуд Клиффс, Нью-Джерси: Прентис-Холл. п. 90. ИСБН 0-13-588187-0.
  10. ^ OS360Sup, стр. 82-85.
  11. ^ OS360Sup, стр. 82.
  12. ^ Корпорация IBM (май 1973 г.). Логика программы: Операционная система IBM System/360 MVT Supervisor (PDF) . стр. 107–137 . Проверено 3 апреля 2019 г.
  13. ^ OSVS1Dig, стр. 2.37-2.39, Подпулы хранения данных VS1.
OS360Sup
OS Release 21 Службы супервизора операционной системы IBM System/360 и инструкции по макросам (PDF) . Справочная библиотека систем IBM (Восьмое изд.). ИБМ. Сентябрь 1974 г. GC28-6646-7.
ОСВС1Диг
Справочный дайджест программиста OS/VS1, выпуск 6 (PDF) . Системы (Шестое изд.). ИБМ. Ноябрь 1975 г. GC24-5091-5.

дальнейшее чтение

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

  • Справочник по управлению памятью, Руководство для начинающих. Распределение