Введение
Сегмент хранения
В вычислительной технике сегмент данных (часто обозначаемый как data) — это часть объектного файла или соответствующего адресного пространства программы, содержащая инициализированные статические переменные, то есть глобальные переменные и статические локальные переменные. Размер этого сегмента определяется размером значений в исходном коде программы и не изменяется во время выполнения. Сегмент данных доступен для чтения и записи, поскольку значения переменных могут быть изменены во время выполнения. Это отличается от сегмента данных, доступного только для чтения (сегмент rodata или rodata), который содержит статические константы, а не переменные; он также отличается от сегмента кода, также известного как сегмент текста, который во многих архитектурах доступен только для чтения. Неинициализированные данные, как переменные, так и константы, вместо этого находятся в сегменте BSS. Исторически сложилось так, что для поддержки пространств адресов памяти, превышающих размер внутреннего регистра адресов, ранние процессоры реализовали систему сегментации, при которой они хранили небольшой набор индексов для использования в качестве смещений к определенным областям. Семейство процессоров Intel 8086 предоставляло четыре сегмента: сегмент кода, сегмент данных, сегмент стека и дополнительный сегмент. Каждый сегмент размещался в определенном месте в памяти выполняемым программным обеспечением, и все инструкции, работающие с данными в этих сегментах, выполнялись относительно начала этого сегмента. Это позволило 16-битному адресному регистру, который обычно мог бы обращаться к 64 КБ памяти, обращаться к 1 МБ памяти. Это сегментирование адресного пространства на отдельные блоки с конкретными задачами перешло в языки программирования того времени, и эта концепция до сих пор широко используется в современных языках программирования.
In computing, a data segment (often denoted data) is a portion of an object file or the corresponding address space of a program that contains initialized static variables, that is, global variables and static local variables. The size of this segment is determined by the size of the values in the program's source code, and does not change at run time. The data segment is read/write, since the values of variables can be altered at run time. This is in contrast to the read only data segment (rodata segment or rodata), which contains static constants rather than variables; it also contrasts to the code segment, also known as the text segment, which is read only on many architectures. Uninitialized data, both variables and constants, is instead in the BSS segment. Historically, to be able to support memory address spaces larger than the native size of the internal address register would allow, early CPUs implemented a system of segmentation whereby they would store a small set of indexes to use as offsets to certain areas. The Intel 8086 family of CPUs provided four segments: the code segment, the data segment, the stack segment and the extra segment. Each segment was placed at a specific location in memory by the software being executed and all instructions that operated on the data within those segments were performed relative to the start of that segment. This allowed a 16 bit address register, which would normally be able to access 64 KB of memory space, to access 1 MB of memory space. This segmenting of the memory space into discrete blocks with specific tasks carried over into the programming languages of the day and the concept is still widely in use within modern programming languages.
Память программы
Память компьютерной программы в основном разделяется на две категории: только для чтения и чтение/запись. Это разделение возникло в ранних системах, где основная программа хранилась в памяти, предназначенной только для чтения, такой как Mask ROM, EPROM, PROM или EEPROM. По мере усложнения систем и загрузки программ из других носителей в оперативную память вместо выполнения непосредственно из ПЗУ, сохранялась идея о том, что некоторые части памяти программы не должны изменяться. Эти части стали текстовым и rodata сегментами программы, а остальная память, доступная для записи, разделялась на несколько других сегментов для выполнения конкретных задач.
Код
Сегмент кода, также известный как текстовый сегмент, содержит исполняемый код и, как правило, доступен только для чтения и имеет фиксированный размер.
Куча
Сегмент кучи содержит динамически выделенную память и обычно начинается в конце сегмента BSS, расширяясь в сторону больших адресов. Управляется он функциями malloc, calloc, realloc и free, которые могут использовать системные вызовы brk и sbrk для изменения его размера (следует отметить, что использование brk/sbrk и единственного сегмента кучи не является обязательным для обеспечения функциональности malloc/calloc/realloc/free; эти функции также могут быть реализованы с помощью mmap/munmap для резервирования и освобождения потенциально несмежных областей виртуальной памяти в виртуальном адресном пространстве процесса). Сегмент кучи совместно используется всеми потоками, общими библиотеками и динамически загружаемыми модулями в рамках одного процесса.
Стеллаж
Сегмент стека содержит стек вызовов, структуру LIFO, обычно расположенную в верхней части памяти. Регистр "указателя стека" отслеживает вершину стека; он изменяется каждый раз, когда значение "помещается" в стек. Набор значений, помещенных в стек для одного вызова функции, называется "стековым кадром". Стеквый кадр состоит как минимум из адреса возврата. Автоматические переменные также выделяются в стеке. Сегмент стека традиционно примыкал к сегменту кучи, и они росли навстречу друг другу; когда указатель стека встречался с указателем кучи, свободная память заканчивалась. С большими адресными пространствами и использованием виртуальной памяти они, как правило, располагаются более свободно, но всё ещё обычно растут в сходящемся направлении. На стандартной PC x86 архитектуре стек растет в сторону меньших адресов, то есть более новые элементы, находящиеся глубже в цепочке вызовов, располагаются по численно меньшим адресам и ближе к куче. На некоторых других архитектурах он растет в противоположном направлении.
Перевод на другие языки
Некоторые интерпретируемые языки предоставляют аналогичные возможности для сегмента данных, в частности Perl и Ruby. В этих языках включение строки DATA (Perl) или END (Ruby, старый Perl) обозначает конец сегмента кода и начало сегмента данных. Выполняется только содержимое до этой строки, а содержимое исходного файла после этой строки становится доступным как файловый объект: PACKAGE::DATA в Perl (например, main::DATA) и DATA в Ruby. Это можно рассматривать как разновидность here-документа (файлового литерала).