Может ли память, выделенная через mmap, перекрывать сегмент данных - PullRequest
5 голосов
/ 20 февраля 2012

Функция malloc использует функции sbrk и mmap.Теперь функция sbrk увеличивает или уменьшает сегмент данных.Так что растет линейно.Теперь мой вопрос: всегда ли поддерживается эта линейность или, например, вызов mmap может выделить память, перекрывающую сегмент данных?

Я говорю о многопоточных программах, работающих на многоядерных системах. В этом блоге говорится о некоторых серьезных недостатках sbrk для многопоточных программ и указывается, что вполне возможно, что память, выделенная с помощью sbrk, может быть смешана с памятью, выделенной с помощью mmap (Куча sbrk может стать прерывистой, поскольку область mmaped или общий объект препятствует росту кучи ).

Ответы [ 2 ]

12 голосов
/ 20 февраля 2012

В этом блоге не видно леса за деревьями;только реализация malloc может вызывать sbrk с ненулевым аргументом.Точнее говоря, большинство malloc реализаций для Unix перестанут работать правильно (и под этим я подразумеваю "ваша программа потерпит крах"), если код приложения вызовет sbrk с ненулевым аргументом.Если вы хотите сделать большое выделение непосредственно из ОС, вы должны использовать для этого mmap.

(Это правда, что в многопоточной программе malloc необходимовнутренне обернуть мьютекс вокруг его вызовов к sbrk, но это деталь реализации. POSIX говорит, что malloc поточно-ориентирован, это важно для программиста приложения.)

mmap не будет выделять память перекрытие области brk, если вы не используете MAP_FIXED.Если вы используете MAP_FIXED, и ваша программа взрывается, вы получаете возможность сохранить все части.

Ядро пытается избежать этого, но mmap при нормальной работе может предположительно выделить память близко к вершинеbrk площадь.Если это произойдет, последующий вызов sbrk, который столкнется с областью mmap, будет сбой . не будет выделять непрерывную память.Хорошие реализации malloc должны обнаружить это условие и начать использовать mmap для всего.Я на самом деле не пробовал, но тестовую программу было бы довольно легко написать.

3 голосов
/ 21 февраля 2012

всегда ли поддерживается эта линейность, или, например, вызов mmap может выделить память, перекрывающую сегмент данных?

Наблюдаемое поведение состоит в том, что область brk всегда линейна. Детали реализации: Если увеличение области brk невозможно, например, из-за блокирования отображения, glibc переключится на mmap-only. Небольшие выделения (<128 КБ), по-видимому, получаются с помощью glibc через brk, если это возможно, поэтому блокирует это с помощью: </p>

#include <stdio.h>
#include <stdlib.h>
#include <unistd.h>
#include <sys/mman.h>

int main(void)
{
        int i;
        for (i = 0; i < 1024; ++i) {
                malloc(2048);
                if (i == 512) {
                        void *r, *end = sbrk(0);
                        r = mmap(end, 4096, PROT_NONE,
                           MAP_PRIVATE|MAP_ANONYMOUS, 0, 0);
                }
        }
}

в стринге даёт действительно

[...]
brk(0x1e7d000)                          = 0x1e7d000
mmap(0x1e7d000, 4096, PROT_NONE, MAP_PRIVATE|MAP_ANONYMOUS, 0, 0) = 0x1e7d000
brk(0x1e9e000)                          = 0x1e7d000   <-- (!)
mmap(NULL, 1048576, PROT_READ|PROT_WRITE, MAP_PRIVATE|MAP_ANONYMOUS, -1, 0) = 0x7fbfd9bc9000
Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...