BSS, стек, куча, данные, код / ​​текст - где каждый из них начинается в памяти? - PullRequest
7 голосов
/ 08 февраля 2010

Сегменты памяти - BSS, стек, куча, данные, код / ​​текст (есть ли еще?)

Скажите, что у меня 128 МБ ОЗУ, может кто-нибудь сказать мне:

  • Сколько памяти выделено для каждого из этих сегментов памяти?

  • Где они начинаются? Пожалуйста, укажите диапазон адресов или что-то подобное для большей ясности.

  • Какие факторы влияют, с чего начать?

Ответы [ 2 ]

5 голосов
/ 08 февраля 2010

Этот вопрос зависит от количества используемых переменных. Поскольку вы не указали, какой компилятор, язык или даже операционную систему, это сложно определить! Все это зависит от операционной системы, которая отвечает за управление памятью приложений. Короче говоря, нет определенного ответа на этот вопрос, подумайте об этом, компилятор / компоновщик во время выполнения просит операционную систему выделить блок памяти, что распределение зависит от того, сколько существует переменных, насколько они велики, область применения и использование переменных. Например, эта простая программа на C, в файле с именем simpletest.c:

#include <stdio.h>
int main(int argc, char **argv){
   int num = 42;
   printf("The number is %d!\n", num);
   return 0;
}

Предположим, что среда была основана на Unix / Linux и была скомпилирована следующим образом:

gcc -o simpletest simpletest.c

Если вы введете objdump или nm в двоичном образе simpletest, вы увидите разделы исполняемого файла, в данном случае 'bss', 'text'. Запомните размеры этих разделов, теперь добавьте int var[100]; к приведенному выше коду, перекомпилируйте и еще раз введите objdump или nm, вы обнаружите, что появился раздел data - почему? потому что мы добавили переменную типа массива int с 100 элементами.

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

Короче говоря, ОС вызывает выстрел на управление памятью!

2 голосов
/ 30 августа 2013

вы можете получить всю эту информацию, составляющую вашу программу

# gcc -o hello hello.c  // you might compile with -static for simplicity 

и затем readelf:

# readelf -l hello
Elf file type is EXEC (Executable file)
Entry point 0x80480e0
There are 3 program headers, starting at offset 52

Program Headers:
  Type           Offset   VirtAddr   PhysAddr   FileSiz MemSiz  Flg Align
  LOAD           0x000000 0x08048000 0x08048000 0x55dac 0x55dac R E 0x1000
  LOAD           0x055dc0 0x0809edc0 0x0809edc0 0x01df4 0x03240 RW  0x1000
  NOTE           0x000094 0x08048094 0x08048094 0x00020 0x00020 R   0x4

Section to Segment mapping:
  Segment Sections...
   00     .init .text .fini .rodata __libc_atexit __libc_subfreeres .note.ABI-tag
   01     .data .eh_frame .got .bss
   02     .note.ABI-tag

Выходные данные показывают общую структуру привет. Первый программный заголовок соответствует сегменту кода процесса, который будет загружен из файла со смещением 0x000000 в область памяти, которая будет отображена в адресное пространство процесса по адресу 0x08048000. Сегмент кода будет иметь размер 0x55dac и должен быть выровнен по странице (0x1000). Этот сегмент будет включать в себя сегменты ELF .text и .rodata, которые обсуждались ранее, а также дополнительные сегменты, созданные во время процедуры связывания. Как и ожидалось, он помечен только для чтения (R) и исполняемым файлом (X), но недоступен для записи (W).

Второй заголовок программы соответствует сегменту данных процесса. Загрузка этого сегмента выполняется так же, как указано выше. Однако обратите внимание, что размер сегмента составляет 0x01df4 в файле и 0x03240 в памяти. Это связано с разделом .bss, который должен быть обнулен и поэтому не должен присутствовать в файле. Сегмент данных также будет выровнен по странице (0x1000) и будет содержать сегменты ELF .data и .bss. Он будет помечен для чтения и записи (RW). Третий заголовок программы является результатом процедуры связывания и не имеет отношения к этому обсуждению.

Если у вас есть файловая система proc, вы можете проверить это, если «Hello World» будет работать достаточно долго (подсказка: gdb), с помощью следующей команды:

# cat /proc/`ps -C hello -o pid=`/maps
08048000-0809e000 r-xp 00000000 03:06 479202     .../hello
0809e000-080a1000 rw-p 00055000 03:06 479202     .../hello
080a1000-080a3000 rwxp 00000000 00:00 0
bffff000-c0000000 rwxp 00000000 00:00 0

Первая отображаемая область - это сегмент кода процесса, вторая и третья - это сегмент данных (data + bss + heap), а четвертая, которая не имеет соответствия в файле ELF, - это стек. Дополнительную информацию о запущенном процессе приветствия можно получить с помощью GNU time, ps и /proc/pid/stat.

.

пример взят из: http://www.lisha.ufsc.br/teaching/os/exercise/hello.html

...