Как устроена виртуальная память процессов

Операционная система довольно умная штука. Она позволяет полностью изолировать физическую память, которую занимают процессы, друг от друга в виртуальные «контейнеры».

Это необходимо по нескольким причинам:

  1. Безопасность. Процессы не смогут переписать память друг друга, а тем более прочитать. Представьте, что вредоносное ПО, попавшее на диск, сможет прочитать ячейки памяти с вашими сообщениями в мессенджере, то есть из другого процесса. Это совершенно недопустимо.
  2. Использование 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 столбца:

  1. Адрес памяти
  2. Размер
  3. Права
  4. Имя файла откуда взят сегмент (или anon если это анонимная память)

С адресом все понятно, это адрес сегмента памяти в шестнадцатеричном формате. Размер — это размер сегмента в килобайтах (K). 4K = 4096 байт, 10244K ≈ 10 МБ.

А вот права стоит разобрать подробнее:

  1. r— только чтение
  2. r-x чтение и исполнение
  3. rw- чтение и запись
  4. rwx всё
  5. —x только исполнение
  6. — зарезервировано

И как ориентироваться, что где в этой карте? Вот простая подсказка:

Точно таким же образом вы можете посмотреть карту виртуальной памяти любого процесса в вашей системе, вызвав pmap с любым pid процесса на вашей машине.

Что мы выяснили:

  1. Виртуальная память позволяет изолировать память процессор друг от друга — один процесс не может прочитать память другого.
  2. У каждого процесса своя собственная карта памяти.

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


Опубликовано

в

от

Метки:

Комментарии

Добавить комментарий

Ваш адрес email не будет опубликован. Обязательные поля помечены *