Как sbrk () работает в C ++? - PullRequest
       40

Как sbrk () работает в C ++?

7 голосов
/ 16 января 2010

Где я могу прочитать о sbrk() в деталях?

Как это работает?

В каких ситуациях я бы хотел использовать sbrk() вместо громоздких malloc() и new()?

Кстати, что такое расширение для sbrk()?

Ответы [ 5 ]

8 голосов
/ 16 января 2010

Посмотрите спецификацию для brk / sbrk .

Вызов в основном просит ОС выделить больше памяти для приложения, увеличив предыдущее «значение разрыва» на определенную величину. Это количество (первый параметр) - это объем дополнительной памяти, которую затем получает ваше приложение.

Большинство элементарных реализаций malloc основаны на системном вызове sbrk для получения блоков памяти, которые они разделяют и отслеживают. Функция mmap обычно считается лучшим выбором (именно поэтому mallocs, такие как dlmalloc, поддерживают оба с #ifdef).

Что касается "как это работает", то sbrk на самом простом уровне 1012 * может выглядеть примерно так:

uintptr_t current_break; // Some global variable for your application.
                         // This would probably be properly tracked by the OS for the process
void *sbrk(intptr_t incr)
{
    uintptr_t old_break = current_break;
    current_break += incr;
    return (void*) old_break;
}

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

4 голосов
/ 16 января 2010

sbrk в значительной степени устарел, в наши дни вы бы использовали mmap для отображения некоторых страниц в / dev / zero. Это, конечно, не то, что вы используете вместо malloc и друзей, это скорее способ их реализовать. Также, конечно, он существует только в операционных системах на основе posix, которые заботятся о обратной совместимости с древним кодом.

Если вы считаете, что Malloc и New слишком громоздки, вам следует вместо этого заняться сборкой мусора ... но будьте осторожны, это может привести к снижению производительности, поэтому вам нужно понять, что вы делаете.

1 голос
/ 16 января 2010

Вы пометили этот C ++, так почему бы вам использовать «громоздкий» malloc (), а не новый? Я не уверен, что громоздко в malloc в любом случае; внутренне может быть и так, но зачем тебе это? И если вам все равно (например, по причинам детерминизма), вы можете выделить большой пул и реализовать свой собственный распределитель для этого пула. Конечно, в C ++ вы можете перегрузить оператор new для этого.

sbrk используется для приклеивания библиотеки C к системе управления памятью операционной системы. Поэтому делайте вызовы ОС, а не используйте sbrk (). Что касается того, как это работает, это зависит от системы. Например, если вы используете библиотеку Newlib C (обычно используется в «голых железных» встраиваемых системах с компилятором GNU), вам нужно реализовать sbrk самостоятельно , поэтому, как она работает в этих условиях, зависит от вы до тех пор, пока он достигает требуемого поведения расширения кучи или неудачи.

Как видно из ссылки, она мало что делает и будет чрезвычайно громоздкой для непосредственного использования - вы, вероятно, в конечном итоге включите ее во все функции, которые предоставляет malloc и new. любой случай.

1 голос
/ 16 января 2010

Вы никогда не хотите использовать sbrk вместо malloc или free. Он непереносим и обычно используется только разработчиками стандартной библиотеки C или в тех случаях, когда он недоступен. Это очень хорошо описано на странице man :

Описание

brk () устанавливает конец сегмент данных до значения, указанного end_data_segment, когда это значение разумно, система имеет достаточно памяти и процесс не превышать максимальный размер данных (см. setrlimit (2)).

sbrk () увеличивает данные программы пробел с приращением байтов. sbrk () не системный вызов, это просто библиотека C обертка. Вызов sbrk () с Приращение 0 может использоваться, чтобы найти текущее местоположение перерыва программы.

Возвращаемое значение

В случае успеха brk () возвращает ноль, а sbrk () возвращает указатель на начало новой области. По ошибке, -1 возвращается, и для errno установлено значение ENOMEM.

Наконец, malloc и free не громоздки - они являются стандартным способом выделения и освобождения памяти в C. Даже если вы хотите реализовать свой собственный распределитель памяти, лучше всего использовать malloc и free в качестве основы - общий подход состоит в том, чтобы выделять большой кусок за раз с malloc и обеспечивать выделение памяти из него (это то, что обычно используют субраспределители или пулы)


В отношении происхождения имени sbrk (или его двоюродного брата brk), оно может иметь какое-то отношение к тому факту, что конец кучи помечен указателем, известным как "break". Куча начинается сразу после сегментов BSS и обычно увеличивается в направлении стека.

0 голосов
/ 16 января 2010

Это зависит от того, что вы подразумеваете под malloc как «громоздкий». sbrk обычно больше не используется напрямую, если только вы не реализуете свой собственный распределитель памяти: IE, оператор переопределяет «new». Даже тогда я мог бы использовать malloc, чтобы дать мне первоначальную память.

Если вы хотите узнать, как реализовать malloc () поверх sbrk (), посмотрите http://web.ics.purdue.edu/~cs354/labs/lab6/, который является упражнением для этого.

В современной системе вы не должны касаться этого интерфейса. Поскольку вы вызываете malloc и new громоздки, я подозреваю, что у вас недостаточно опыта, чтобы безопасно и правильно использовать sbrk для вашего кода.

...