Операционная система довольно умная штука. Она позволяет полностью изолировать физическую память, которую занимают процессы, друг от друга в виртуальные «контейнеры».
Это необходимо по нескольким причинам:
- Безопасность. Процессы не смогут переписать память друг друга, а тем более прочитать. Представьте, что вредоносное ПО, попавшее на диск, сможет прочитать ячейки памяти с вашими сообщениями в мессенджере, то есть из другого процесса. Это совершенно недопустимо.
- Использование swap. Это файл на жестком диске, в который выгружается все, что не поместилось в RAM или все что ОС посчитала ненужным здесь и сейчас, и решила выгрузить на диск.
Именно поэтому, операционная система создает иллюзию наличия всей памяти у каждого процесса, создавая для него свою карту памяти, которую процесс может использовать.
Давайте попробуем посмотреть как это работает на практике. Создадим не сложную программу на C и скомпилируем ее:
#include <stdio.h>
#include <stdlib.h>
#include <unistd.h>
int global_var = 42; // глобальная переменная — в data segment
int main() {
int local_var = 100; // локальная — в stack
int *heap_var = malloc(1024 * 1024 * 10); // выделяем 10 МБ в heap
printf("PID процесса: %d\n", getpid());
printf("Нажми Enter, чтобы запустить pmap...\n");
getchar();
// Заполняем выделенную память, чтобы она реально выделилась
for (int i = 0; i < 1024 * 1024 * 10; i++) {
heap_var[i] = i % 256;
}
printf("Память заполнена. Нажми Enter для выхода...\n");
getchar();
free(heap_var);
return 0;
}
Скомпилируйте эту программу:
gcc test.c -o test
И запустите, выполнив:
./test
Далее, в соседнем терминале выполните:
pmap <ID который выдала ./test в соседнем терминале>
Вы увидите на экране нечто подобное:
0000575fa7b47000 4K r---- test
0000575fa7b48000 4K r-x-- test
0000575fa7b49000 4K r---- test
0000575fa7b4a000 4K r---- test
0000575fa7b4b000 4K rw--- test
0000575fd8039000 132K rw--- [ anon ]
000070d8f6bff000 10244K rw--- [ anon ]
000070d8f7600000 160K r---- libc.so.6
000070d8f7628000 1568K r-x-- libc.so.6
000070d8f77b0000 316K r---- libc.so.6
000070d8f77ff000 16K r---- libc.so.6
000070d8f7803000 8K rw--- libc.so.6
000070d8f7805000 52K rw--- [ anon ]
000070d8f7977000 12K rw--- [ anon ]
000070d8f798d000 8K rw--- [ anon ]
000070d8f798f000 16K r---- [ anon ]
000070d8f7993000 8K r---- [ anon ]
000070d8f7995000 8K r-x-- [ anon ]
000070d8f7997000 4K r---- ld-linux-x86-64.so.2
000070d8f7998000 172K r-x-- ld-linux-x86-64.so.2
000070d8f79c3000 40K r---- ld-linux-x86-64.so.2
000070d8f79cd000 8K r---- ld-linux-x86-64.so.2
000070d8f79cf000 8K rw--- ld-linux-x86-64.so.2
00007fff768d7000 132K rw--- [ stack ]
ffffffffff600000 4K --x-- [ anon ]
всего 12936K
Коротко разберем как читать вывод. Весь вывод делится на 4 столбца:
- Адрес памяти
- Размер
- Права
- Имя файла откуда взят сегмент (или anon если это анонимная память)
С адресом все понятно, это адрес сегмента памяти в шестнадцатеричном формате. Размер — это размер сегмента в килобайтах (K). 4K = 4096 байт, 10244K ≈ 10 МБ.
А вот права стоит разобрать подробнее:
- r— только чтение
- r-x чтение и исполнение
- rw- чтение и запись
- rwx всё
- —x только исполнение
- — зарезервировано
И как ориентироваться, что где в этой карте? Вот простая подсказка:

Точно таким же образом вы можете посмотреть карту виртуальной памяти любого процесса в вашей системе, вызвав pmap с любым pid процесса на вашей машине.
Что мы выяснили:
- Виртуальная память позволяет изолировать память процессор друг от друга — один процесс не может прочитать память другого.
- У каждого процесса своя собственная карта памяти.
Таким образом, надеюсь, эта маленькая заметка вам поможет вам чуть глубже разобраться во внутренней природе виртуальной памяти процессов.
Добавить комментарий