Структура памяти программы C (стек и куча) - PullRequest
0 голосов
/ 21 апреля 2020

Являются ли стек и куча общими для всей системы или стек и куча созданы специально для каждого созданного процесса?

1 Ответ

3 голосов
/ 25 апреля 2020

Краткий ответ : да , каждый процесс имеет свой собственный стек (это должно быть так, поскольку каждый работающий объект должен иметь его) и кучу.

Длинный ответ : читать дальше.

Адресное пространство

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

Когда я говорю, что процесс владеет адресным пространством, это означает, что один процесс не может заглянуть внутрь адресного пространства другого процесса. Эта защита памяти выполняется аппаратно, с использованием специального устройства, называемого блок управления памятью (MMU), который обычно является частью ЦП. Можно сказать, что адресное пространство является абстракцией детали аппаратной реализации, называемой MMU.

Упомянутая абстракция - адресное пространство - дает каждому процессу ощущение, что он имеет доступный линейный массив байтов, пронумерованный от 0 до 2. ^ 64-1 (на 64-битных системах). Современные системы редко снабжаются таким объемом памяти, поэтому обычно физическая память поддерживает только часть этого адресного пространства.

Всякий раз, когда процесс обращается к памяти, которая недопустима в его адресном пространстве, он завершается: сбой . Абстракция сбоя (программное обеспечение люди любят абстракции) получает сигнал - SIGSEGV («Нарушение сегментации») в случае недопустимого доступа к памяти.

Файловая система / pro c

Специальный тип файловой системы под названием proc обычно монтируется на /proc. Чтобы продемонстрировать адресные пространства и их расположение, я запускаю произвольную программу,

$ sleep 10000&
[1] 12010

Запуск ее в фоновом режиме (&) дает мне идентификатор процесса, который я использую для перехода в каталог процесса в каталоге /proc,

$ cd /proc/12010

Обратите внимание, что /proc - это не каталог на диске, а нечто, имеющее смешное имя (идентификатор процесса), похожее на каталог, каталог и содержащий файлы и подкаталоги, которые представляют пользователю атрибуты процесса. Здесь нас интересует макет памяти адресного пространства - допустимые регионы в адресном пространстве.

Это то, что показывает файл `/ proc / PID / maps,

$ cat maps 
55b782825000-55b782827000 r--p 00000000 fd:00 1180965                    /usr/bin/sleep
55b782827000-55b78282b000 r-xp 00002000 fd:00 1180965                    /usr/bin/sleep
55b78282b000-55b78282d000 r--p 00006000 fd:00 1180965                    /usr/bin/sleep
55b78282e000-55b78282f000 r--p 00008000 fd:00 1180965                    /usr/bin/sleep
55b78282f000-55b782830000 rw-p 00009000 fd:00 1180965                    /usr/bin/sleep
55b783115000-55b783136000 rw-p 00000000 00:00 0                          [heap]
7ff262d19000-7ff26fcfe000 r--p 00000000 fd:00 1188440                    /usr/lib/locale/locale-archive
7ff26fcfe000-7ff26fd23000 r--p 00000000 fd:00 1183177                    /usr/lib64/libc-2.30.so
7ff26fd23000-7ff26fe72000 r-xp 00025000 fd:00 1183177                    /usr/lib64/libc-2.30.so
7ff26fe72000-7ff26febc000 r--p 00174000 fd:00 1183177                    /usr/lib64/libc-2.30.so
7ff26febc000-7ff26febd000 ---p 001be000 fd:00 1183177                    /usr/lib64/libc-2.30.so
7ff26febd000-7ff26fec0000 r--p 001be000 fd:00 1183177                    /usr/lib64/libc-2.30.so
7ff26fec0000-7ff26fec3000 rw-p 001c1000 fd:00 1183177                    /usr/lib64/libc-2.30.so
7ff26fec3000-7ff26fec9000 rw-p 00000000 00:00 0 
7ff26feeb000-7ff26feed000 r--p 00000000 fd:00 1180257                    /usr/lib64/ld-2.30.so
7ff26feed000-7ff26ff0d000 r-xp 00002000 fd:00 1180257                    /usr/lib64/ld-2.30.so
7ff26ff0d000-7ff26ff15000 r--p 00022000 fd:00 1180257                    /usr/lib64/ld-2.30.so
7ff26ff16000-7ff26ff17000 r--p 0002a000 fd:00 1180257                    /usr/lib64/ld-2.30.so
7ff26ff17000-7ff26ff18000 rw-p 0002b000 fd:00 1180257                    /usr/lib64/ld-2.30.so
7ff26ff18000-7ff26ff19000 rw-p 00000000 00:00 0 
7ffffb0e8000-7ffffb10a000 rw-p 00000000 00:00 0                          [stack]
7ffffb1eb000-7ffffb1ee000 r--p 00000000 00:00 0                          [vvar]
7ffffb1ee000-7ffffb1ef000 r-xp 00000000 00:00 0                          [vdso]
ffffffffff600000-ffffffffff601000 r-xp 00000000 00:00 0                  [vsyscall]

Эта строка, например,

55b78282f000-55b782830000 rw-p 00009000 fd:00 1180965                    /usr/bin/sleep

представляет собой отображение r ead- w общих глобальных данных в процесс, заполняемый с /usr/bin/sleep (со смещением в файле, который здесь не показан).

Другое отображение,

55b782827000-55b78282b000 r-xp 00002000 fd:00 1180965                    /usr/bin/sleep

- это r eadable и e x ecutable - код , который заполняется из того же двоичного файла. Другие строки в файле показывают сопоставления, взятые из общих библиотек, которые содержат сопоставимые артефакты.

Наконец, есть два сопоставления stack и heap, которые не заполняются из файла, а являются анонимными выделениями, созданными ядро, когда процесс был создан.

...