Ядро Linux в комментариях

       

Динамическая память пространства пользователя и пространства ядра


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

В Linux, как и в других разновидностях Unix, область данных процесса подразделяется на две части разного назначения — на стек и кучу. Чтобы предотвратить столкновение этих частей, стек начинается с верхней части (фактически, рядом с ней) доступного адресного пространства и растет вниз, в область младших адресов, а куча начинается непосредственно над сегментом кода и растет вверх. Между кучей и стеком находится «ничейная земля» обычно неиспользуемой памяти, хотя память может быть распределена и в этом месте с помощью mmap.

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

#include <stdio.h> /* printf() */ #include <stdlib.h> /* malloc() */ static void one(void * p, const char * description) { printf("%10p: %s\n", p, description); }

int main(void) { int i; int j; one(&i, "A stack variable, \"i\""); one(&j, "Next stack variable, \"j\""); one((void *) one, "The function \"one\""); one((void *) main, "The function \"main\""); one(malloc(1), "First heap allocation"); one(malloc(1), "Second heap allocation"); return 0; }

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

0xbffff824: A stack variable, "i" 0xbffff820: Next stack variable, "j" 0x80484a0: The function "one" 0x80484bc: The function "main" 0x80496f8: First heap allocation 0x8049708: Second heap allocation

Очевидно, что стек, грубо говоря, начинается примерно с адреса 0хC0000000 и растет вниз, код начинается примерно с 0x8000000, а куча, как мы и утверждали, начинается немного выше кода и растет вверх.



Содержание раздела