Как работает sbrk () на C++?
где я могу прочитать о sbrk()
в некоторых деталях?
как именно это работает?
в каких ситуациях я хотел бы использовать sbrk()
вместо громоздких malloc()
и new()
?
кстати, что такое расширения для sbrk()
?
5 ответов
посмотреть спецификация для brk / sbrk.
вызов в основном просит ОС выделить немного больше памяти для приложения, увеличив Предыдущее "значение перерыва" на определенную сумму. Эта сумма (первый параметр) - это объем дополнительной памяти, которую получает ваше приложение.
большинство рудиментарных реализаций malloc строятся на системном вызове sbrk, чтобы получить блоки памяти, которые они разделяют и отслеживают. The вызов mmap функция обычно принимается как лучший выбор (Именно поэтому mallocs, такие как dlmalloc, поддерживают оба с #ifdef).
Что касается "как это работает", sbrk в его самый простой уровень может выглядеть так:
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;
}
современные операционные системы сделали бы гораздо больше, например, отображали бы страницы в адресное пространство и добавляли бы информацию отслеживания для каждого выделенного блока памяти.
sbrk в значительной степени устарел, в наши дни вы бы использовали mmap для отображения некоторых страниц из /dev / zero. Это, конечно, не то, что вы используете вместо malloc и друзей, это скорее способ их реализации. Кроме того, конечно, он существует только в операционных системах на основе posix, которые заботятся о обратной совместимости с древним кодом.
Если вы найдете Malloc и New слишком громоздкими, вы должны вместо этого посмотреть на сборку мусора... но будьте осторожны, существует потенциальная стоимость производительности это, поэтому вам нужно понять, что вы делаете.
вы никогда не хотите использовать sbrk
вместо malloc
или free
. Он не переносится и обычно используется только разработчиками стандартной библиотеки C или в случаях, когда он недоступен. Это описано довольно хорошо в его man page:
описание
brk () устанавливает конец сегмент данных до значения, указанного end_data_segment, когда это значение разумная система имеет достаточно память и процесс не превышать его максимальный размер данных (см. setrlimit (2)).
sbrk () увеличивает данные программы пробел по байтам приращения. sbrk () не системный вызов, это просто библиотека C обертка. Вызов sbrk () с помощью инкремент 0 можно использовать для поиска текущее местоположение программы.
Возвращаемое Значение
на успех, BRK() возвращает ноль, и sbrk () возвращает указатель на начало новая область. При ошибке, Возвращается значение -1, а errno - ENOMEM.
наконец,malloc
и free
не громоздки - они стандартный способ выделения и освобождения памяти в C. Даже если вы хотите реализовать свой собственный распределитель памяти, то лучше всего использовать malloc
и free
в качестве основы-общий подход заключается в выделении большого куска за раз с malloc
и обеспечить выделение памяти из него (это то, что обычно субаллокаторы или пулы реализовать)
Re происхождение имени sbrk
(или его двоюродный брат brk
), это может быть связано с тем, что конец кучи отмечен указателем, известным как "перерыв". Куча начинается сразу после сегментов BSS и обычно растет к стеку.
вы пометили этот C++, так почему бы вам использовать "громоздкий" malloc (), а не новый? Я не уверен, что это громоздкое про malloc в любом случае; внутренне может и так, но почему вас это волнует? И если вам было все равно (например, по причинам детерминизма), вы могли бы выделить большой пул и реализовать свой собственный распределитель для этого пула. В C++, конечно, вы можете перегрузить новый оператор для этого.
sbrk используется для приклеивания библиотеки C к памяти ОС базовой системы управление. Поэтому делайте вызовы ОС, а не с помощью sbrk(). Что касается того, как это работает, это зависит от системы. Если, например, вы используете библиотеку Newlib C (обычно используемую в встроенных системах "голого металла" с компилятором GNU), вы должны реализовать sbrk самостоятельно, так как он работает в этих обстоятельствах, зависит от вас, пока он достигает требуемого поведения расширения кучи или сбоя.
Как вы можете видеть по ссылке, это не много и будет очень громоздко использовать напрямую-вы, вероятно, в конечном итоге оберните его во все функции, которые предоставляют malloc и new в любом случае.
Это зависит от того, что вы подразумеваете под "громоздким"malloc. sbrk обычно больше не используется напрямую, если вы не реализуете свой собственный распределитель памяти: т. е. оператор, переопределяющий "new". Даже тогда я, возможно, использую malloc, чтобы дать мне первоначальную память.
Если вы хотите увидеть, как реализовать malloc () поверх sbrk (), проверьтеhttp://web.ics.purdue.edu / ~cs354 / labs / lab6/ что является упражнением, проходящим через это.
о современной системе вы не должны касаться этого интерфейса, хотя. Поскольку вы вызываете malloc и new cumbersome, я подозреваю, что у вас нет всего необходимого опыта для безопасного и правильного использования sbrk для вашего кода.