[Linux] Адресное пространство процесса

[Linux] Адресное пространство процесса

Понятие адресного пространства процесса

Будучи менеджером ресурсов компьютерного программного и аппаратного обеспечения, операционная система, конечно же, должна управлять распределением памяти для каждого процесса. Следовательно, она должна иметь структуру данных, описывающую распределение памяти для каждого процесса. Эта структура данных ядра представляет собой адресное пространство процесса. В операционной системе Linux имя переменной этой структуры данных — mm_struct.

Реализация адресного пространства процесса

Чтобы лучше управлять распределением памяти, реализация mm_struct использует следующую стратегию:

  • Как структура данных, описывающая распределение памяти, она описывает все пространство памяти.
  • Используйте непрерывные линейные адреса для описания адресов в памяти.
  • Все описанные адреса являются виртуальными адресами.

Псевдокод mm_struct выглядит следующим образом:

struct mm_struct
{
    
    
    long code_begin; //代码区起始地址
    long code_end;	 //代码区结束地址
    //...
    long brk_begin;  //堆区起始地址
    long brk_end;	 //堆区结束地址
    long brk_begin;  //栈区起始地址
    long brk_end;	 //栈区结束地址
}

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

изображение-20230826134746803

Хотя адресное пространство процесса описывает виртуальный адрес, процессу все равно необходимо найти свои собственные данные и код по фактическому адресу в памяти. Поэтому операционная система использует сопоставление для преобразования виртуального адреса в фактический адрес памяти. Инструмент под названием во время сопоставления используется таблица страниц.Таблица страниц записывает сопоставление между виртуальными адресами и фактическими адресами памяти следующим образом:

изображение-20230826135906135

Понимание копирования при записи

Сначала напишите следующий код, чтобы наблюдать явление копирования при записи:

#include <stdio.h>
#include <unistd.h>
#include <assert.h>

int main()
{
    
    
  int val = 100;
  pid_t id = fork();
  assert(id >= 0);
  if (id == 0)
  {
    
    
    //子进程
    while(1)
    {
    
    
      printf("我是子进程,pid:%d, ppid:%d, val:%d, &val:%p\n", getpid(), getppid(), val, &val);
      sleep(1);
      val = 200;
    }
  }
  else if (id > 0)
  {
    
    
    while(1)
    {
    
    
      printf("我是父进程,pid:%d, ppid:%d, val:%d, &val:%p\n", getpid(), getppid(), val, &val);
      sleep(1);
    }
  }
  return 0;
}

Скомпилируйте и запустите приведенный выше код, чтобы увидеть это явление:

изображение-20230826141508478

  • После того как дочерний процесс изменяет значение переменной val, изменение значения val дочернего процесса не влияет на значение val родительского процесса.
  • Адреса val родительского и дочернего процессов одинаковы, но значения разные.

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

Прежде всего, поскольку все адреса в адресном пространстве процесса являются виртуальными адресами, данные, считываемые родительским и дочерним процессами по одному и тому же адресу, кажутся разными. При создании дочернего процесса используемое адресное пространство процесса и таблица страниц копируются из родительского процесса следующим образом:

изображение-20230826142401503

Когда дочерний процесс изменяет val, операционная система повторно открывает пространство для дочернего процесса для записи измененного значения, а затем изменяет фактический адрес, сопоставленный в таблице страниц, для реализации копирования при записи, следующим образом:

изображение-20230826142642452

Зачем существует адресное пространство процесса?

Чтобы понять, почему существует адресное пространство процесса, мы должны сначала понять две вещи:

Суть malloc

Поскольку ресурсы памяти ограничены, чтобы уменьшить бесполезную трату памяти, операционная система при подаче заявки на память с помощью malloc заполняет только адрес в виртуальном адресе таблицы страниц, а фактический адрес памяти в таблице страниц является вакантным. Ожидая, пока процесс его использует, выделите кусок места и заполните фактический адрес в таблицу страниц. Это позволяет избежать непроизводительной траты пространства, возникающей, когда процесс обращается за пространством, но не использует его.

Адресное пространство исполняемой программы

Когда исходный код компилируется, код и данные компилируются согласно соответствующему методу адресации, который был запрограммирован в виртуальном адресном пространстве.

В системах Linux вы можете использовать objdumop -S 可执行程序名виртуальный адрес программы для просмотра:

изображение-20230826155041035

После того, как процесс начнет выполняться, ЦП сначала выполняет виртуальный адрес записи, который также содержит адрес. ЦП начнет переходить по таблице страниц через содержимое, записанное в адресе входа, а затем нормально выполнять код и данные процесса. .

Зачем существует адресное пространство процесса?

Во-первых, нам нужно знать, как работает операционная система, если нет адресного пространства процесса. Когда нет адресного пространства процесса, не будет и таблицы страниц.После загрузки процесса в память ЦП выполняет его в порядке кода внутри процесса. следующее:

изображение-20230826150931606

  • Во-первых, в этом случае при выполнении кода процесса, если возникнет проблема с кодом и произойдет операция доступа к памяти по дикому указателю, ЦП также выполнит некорректную операцию доступа. Вместе с адресным пространством процесса имеется также таблица страниц.При доступе к любым данным они должны быть сопоставлены через таблицу страниц.Таблица страниц не только хранит отношения сопоставления адреса, но также хранит адрес чтения определенного адреса. Разрешения на запись и т. д., если используется дикий указатель, таблица страниц перехватит его.
  • Во-вторых, в этом случае, если процесс хочет разделить данные по глобальной области, статической области и другим разделам, он должен найти фактический адрес всего блока в физической памяти для разделения, чтобы управление процессом и управление памятью Требуется совместная работа. Но с адресным пространством процесса и таблицей страниц процессу нужно только знать, можно ли разделить адреса в адресном пространстве процесса по регионам, а физической памяти нужно только найти это пространство, независимо от того, где оно находится в памяти. , потому что в конечном итоге все доступы к данным отображаются через таблицы страниц, а управление одним и тем же процессом и управление памятью отделены друг от друга.
  • В-третьих, в этом случае код и данные необходимо различать отдельно. Благодаря адресному пространству процесса и таблице страниц процессу требуется доступ к коду и данным только через адресное пространство процесса.Во всех адресных пространствах процесса адреса разделов кода и данных одинаковы, поэтому все процессы могут видеть. то же самое касается и вашего собственного адресного пространства процесса.

Подведем итог:

  1. Предотвратите произвольный доступ к адресам и защитите физическую память и другие процессы.
  2. Разделите управление процессами и управление памятью.
  3. Предоставьте всем процессам единое представление кода и данных.

рекомендация

отblog.csdn.net/csdn_myhome/article/details/132522396