UNIX против освобождения памяти Windows - PullRequest
7 голосов
/ 25 октября 2008

Насколько я понимаю, в unix, когда память освобождается, память не возвращается обратно в операционную систему, она остается в процессе для повторного использования для следующего вызова malloc.

В Windows я понимаю, что память фактически возвращается операционной системе.

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

РЕДАКТИРОВАТЬ: Спасибо за разъяснения. Я всегда думал, что это вещь ОС (поскольку в UNIX-подобных системах размер процессов никогда не уменьшается, а в Windows).

Ответы [ 9 ]

14 голосов
/ 25 октября 2008

В этом нет большой разницы между Windows и Unix.

В обоих есть два уровня распределения. Операционная система выделяет память процессу большими кусками (одна страница или более; в x86 размер страницы обычно составляет 4096 байт). Библиотеки времени выполнения, работающие внутри процесса, подразделяют это пространство и выделяют его части для вашего кода.

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

В Linux у вас есть brk и mmap. brk контролирует размер большого куска памяти, выделенного вашему процессу; Вы можете расширить или уменьшить его, но только с одного конца. malloc традиционно расширяет этот кусок памяти, когда ему нужно выделять больше памяти, и сокращает его, когда это возможно. Однако, сокращение не легкое; в конце требуется одно однобайтовое несвоевременное выделение, чтобы оно не могло сжиматься, даже если все до этого выделения было освобождено. Это источник мема «Unix не освобождает память».

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

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

6 голосов
/ 25 октября 2008

Обратите внимание, что я знаю гораздо больше о Windows, чем Unix, в дальнейшем ...

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

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

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

4 голосов
/ 25 октября 2008

Все зависит от того, какую библиотеку времени выполнения C вы используете. Нет НИКАКОГО конкретного способа UNIX или WINDOWS. Каждый поставщик компиляторов (HP, SUN, MS, GNU) поставляется со своей собственной библиотекой времени выполнения, которая содержит логику для malloc. каждая реализация malloc будет работать одинаково / по-разному в зависимости от ОС. Ни UNIX / LINUX / Windows не требуется, чтобы бесплатно "фактически вернуть" память обратно в ОС. Это было бы слишком дорого (так как ваш alloc () был бы очень маленькими порциями)

Недавно Mozilla Firefox позаимствовал реализацию malloc () из * BSD OS. Они решили использовать другой malloc, чем тот, который поставлялся их поставщиком компилятора (несколько в данном случае - gcc и VC ++). Так как они хотели определенного поведения, они получили то, что хотели.

2 голосов
/ 25 октября 2008

Как уже упоминалось, это больше связано с реализацией malloc, чем с операционной системой как таковой. В Linux с glibc память фактически всегда возвращается в ОС выше определенного размера: glibc malloc использует mmap для больших выделений (контролируемых MMAP_THRESHOLD), и в этом случае free вызывает munmap, что автоматически освобождает зарезервированную память. Ниже этого порога он использует brk, и в этом случае free не «возвращает» память.

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

http://blogs.msdn.com/oldnewthing/archive/2004/08/22/218527.aspx

2 голосов
/ 25 октября 2008

Единственной операционной системой, в которой вы не можете легко вернуть выделенную память системе, является OS X - цитата Использование памяти Firefox 3 :

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

2 голосов
/ 25 октября 2008

Из этого Управление памятью Статья

Malloc обычно не возвращает освобожденную память операционной системе; он остается в собственности процесса до его завершения. Процесс может использовать его в следующий раз, когда запросит больше памяти, но другие программы не будут иметь к нему доступа, даже если другая память не доступна. Как следствие, объем памяти, занимаемый программой, равен размеру самого большого выделения (ий), сделанного за один раз. Таким образом, всегда разумно освобождать ненужные вам объекты, особенно крупные, как можно скорее, чтобы минимизировать этот след.

Эта статья предполагает, что в Windows, по крайней мере для программы на C, память не возвращается в ОС.

Так что я не уверен относительно вашего обобщения об освобождении памяти Windows.

Тем не менее, вы можете попробовать эмулировать управление памятью UNIX под Microsoft Windows , реализовав системные вызовы низкого уровня sbrk и mmap / munmap в Windows.

1 голос
/ 25 октября 2008

Другие постеры прокомментировали конкретный угол платформы. Но так как вы спрашиваете конкретно о malloc, давайте посмотрим, что говорит стандарт C:

"Свободная функция вызывает освобождение пространства, на которое указывает ptr, то есть доступны для дальнейшего распределения. "

Что кажется довольно четким требованием, чтобы память не возвращалась ОС. Иногда вы видите программы, основанные на этом поведении:

int main(void)
{

    void *p = malloc(AS_MUCH_MEMORY_AS_I_WILL_EVER_NEED);

    if (p != 0)
    {
        free(p);
        /* malloc should always work for rest of program */
    }
}

Однако, когда этот вопрос возник на comp.lang.c, некоторые авторы указали на этот раздел:

"Функция malloc возвращает либо нулевой указатель, либо указатель на выделенное пространство."

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

1 голос
/ 25 октября 2008

Я не знаю о Windows, но в UNIX вызов brk() используется для увеличения памяти в адресном пространстве для использования вызовами malloc().

Я никогда не видел, чтобы эта память возвращалась в ОС, пока процесс не завершится. Обычно это можно увидеть с помощью таких инструментов, как top.

Я подозреваю, что поведение будет таким же для Windows, но я знаю, что Windows имеет другие функции выделения, чем malloc(), которые могут это делать (часть Win32 API).

0 голосов
/ 18 марта 2015

Функция malloc возвращает либо нулевой указатель, либо указатель на выделенное пространство. "

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

Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...