Это не относится к «почти всем ОС». Типы представленных областей памяти довольно типичны, но нет причин, по которым они должны быть в каком-то определенном порядке, и может быть более одного фрагмента данного вида.
В Linux вы можете посмотреть на адресное пространство процесса, cat /proc/$pid/maps
где $pid
находится идентификатор процесса, например, cat /proc/$$/maps
посмотреть на оболочку, из которой вы работаете cat
, или cat /proc/self/maps
посмотреть на cat
собственные отображения процесса. Команда pmap
производит немного более приятный вывод.
08048000-08054000 r-xp 00000000 08:01 828061 /bin/cat
08054000-08055000 r--p 0000b000 08:01 828061 /bin/cat
08055000-08056000 rw-p 0000c000 08:01 828061 /bin/cat
08c7f000-08ca0000 rw-p 00000000 00:00 0 [heap]
b755a000-b7599000 r--p 00000000 08:01 273200 /usr/lib/locale/en_US.utf8/LC_CTYPE
b7599000-b759a000 rw-p 00000000 00:00 0
b759a000-b76ed000 r-xp 00000000 08:01 269273 /lib/tls/i686/cmov/libc-2.11.1.so
b76ed000-b76ee000 ---p 00153000 08:01 269273 /lib/tls/i686/cmov/libc-2.11.1.so
b76ee000-b76f0000 r--p 00153000 08:01 269273 /lib/tls/i686/cmov/libc-2.11.1.so
b76f0000-b76f1000 rw-p 00155000 08:01 269273 /lib/tls/i686/cmov/libc-2.11.1.so
b76f1000-b76f4000 rw-p 00000000 00:00 0
b770b000-b7712000 r--s 00000000 08:01 271618 /usr/lib/gconv/gconv-modules.cache
b7712000-b7714000 rw-p 00000000 00:00 0
b7714000-b7715000 r-xp 00000000 00:00 0 [vdso]
b7715000-b7730000 r-xp 00000000 08:01 263049 /lib/ld-2.11.1.so
b7730000-b7731000 r--p 0001a000 08:01 263049 /lib/ld-2.11.1.so
b7731000-b7732000 rw-p 0001b000 08:01 263049 /lib/ld-2.11.1.so
bfbec000-bfc01000 rw-p 00000000 00:00 0 [stack]
Вы можете увидеть код и данные для чтения и записи (текст и BSS) из исполняемого файла, затем кучи, затем отображенный в память файл, затем немного больше данных для чтения и записи, затем код, данные только для чтения и данные для чтения. запись данных из общей библиотеки (снова текст и BSS), больше данных для чтения и записи, другая общая библиотека (точнее, динамический компоновщик) и, наконец, стек единственного потока.
Код ядра использует свои собственные диапазоны адресов. На многих платформах Linux использует верхнюю часть адресного пространства для ядра, часто верхнюю 1 ГБ. В идеале этого пространства должно быть достаточно для отображения кода ядра, данных ядра, а также системной памяти (ОЗУ) и каждого устройства, отображенного в памяти. На сегодняшних типичных 32-битных ПК это невозможно, для чего требуются искажения, которые представляют интерес только для хакеров ядра.
Пока код ядра обрабатывает системный вызов, в идеале (когда вышеупомянутые искажения отсутствуют) память процесса отображается по тем же адресам. Это позволяет процессам передавать данные в ядро, и ядро может читать из указателя напрямую. Это не большой выигрыш, так как указатели все равно должны быть проверены (так что процесс не может обмануть ядро в чтении из памяти, к которой у процесса не должно быть доступа).
Зоны памяти внутри пространства ядра Linux довольно сложны. Существует несколько различных пулов памяти, и основные различия заключаются не в том, откуда берется память, а в том, с кем она используется. Если вам интересно, начните с LDD3 .
where.c
при использовании Ubuntu 11.04gcc where.c -o where
; сообщает "main at 0x80483c4". Пробовалreadelf -S where
, и он сообщает, скажем "[13] .text PROGBITS 08048310 ...", который выглядит примерно так? Хотя я также получаю "ac at 0xbfb035a0" и "local at 0xbfb0358c", и этот диапазон адресов (0xbf ...), по-видимому, не сообщаетсяreadelf -S
.ac
иav
и автоматическая переменнаяlocal
, вероятно, будут иметь разные адреса при каждом вызове. Большинство современных ядер Linux имеют «рандомизацию расположения адресного пространства», чтобы затруднить использование переполнения буфера.