Книга: Разработка ядра Linux

Дескриптор памяти

Ядро представляет адресное пространство процесса в виде структуры данных, которая называется дескриптором памяти. Эта структура содержит всю информацию, которая относится к адресному пространству процесса. Дескриптор памяти представляется с помощью структуры struct mm_struct, которая определена в файле <linux/sched.h>[81].

Рассмотрим эту структуру с комментариями, поясняющими назначение каждого поля.

struct mm_struct {
 struct vm_area_struct *mmap;        /* список областей памяти */
 struct rb_root        mm_rb;        /* красно-черное дерево
                                        областей памяти */
 struct vm_area_struct *mmap_cache;  /* последняя использованная
                                        область памяти */
 unsigned long         free_area_cache; /* первый незанятый участок
                                           адресного пространства */
 pgd_t                 *pgd;         /* глобальный каталог страниц */
 atomic_t              mm_users;     /* счетчик пользователей адресного
                                        пространства */
 atomic_t              mm_count;     /* основной счетчик использования */
 int                   map_count;    /* количество областей памяти */
 struct rw_semaphore   mmap_sem;     /* семафор для областей памяти */
 spinlock_t            page_table_lock; /* спин-блокировка
                                           таблиц страниц */
 struct list_head      mmlist;       /* список всех структур mm_struct */
 unsigned long         start_code;   /* начальный адрес сегмента кода */
 unsigned long         end code;     /* конечный адрес сегмента кода */
 unsigned long         start_data;   /* начальный адрес сегмента данных */
 unsigned long         end_data;     /* конечный адрес сегмента данных */
 unsigned long         start_brk;    /* начальный адрес сегмента "кучи" */
 unsigned long         brk;          /* конечный адрес сегмента "кучи" */
 unsigned long         start_stack;  /* начало стека процесса */
 unsigned long         arg_start;    /* начальный адрес
                                        области аргументов */
 unsigned long         arg_end;      /* конечный адрес
                                        области аргументов */
 unsigned long         env_start;    /* начальный адрес
                                        области переменных среды */
 unsigned long         env_end;      /* конечный адрес
                                        области переменных среды */
 unsigned long         rss;          /* количество физических страниц памяти */
 unsigned long         total_vm;     /* общее количество страниц памяти */
 unsigned long         locked_vm;    /* количество заблокированных страниц
                                        памяти */
 unsigned long         def_flags;    /* флаги доступа, используемые
                                        по умолчанию */
 unsigned long         cpu_vm_mask;  /* маска отложенного переключения
                                        буфера TLB */
 unsigned long         swap_address; /* последний сканированный адрес */
 unsigned              dumpable:1;   /* можно ли создавать файл core? */
 int                   used_hugetlb; /* используются ли гигантские
                                        страницы памяти (hugetlb)? */
 mm_context_t          context;      /* данные, специфичные для аппаратной
                                        платформы */
 int                   core_waiters; /* количество потоков, ожидающих на
                                        создание файла core */
 struct completion     *core_startup_done; /* условная переменная начала
                                              создания файла core */
 struct completion     core_done;    /* условная переменная завершения
                                        создания файла core */
 rwlock_t              ioctx_list_lock; /* блокировка списка асинхронного
                                           ввода-вывода (AIO) */
 struct kioctx         *ioctx_list;  /* список асинхронного ввода-вывода (AIO) */
 struct kioctx         default_kioctx; /* контекст асинхронного ввода-
                        вывода, используемый по умолчанию */
};

Поле mm_users — это количество процессов, которые используют данное адресное пространство. Например, если одно и то же адресное пространство совместно используется двумя потоками, то значение поля mm_users равно двум. Поле mm_count — это основной счетчик использования структуры mm_struct. Наличие пользователей структуры, которым соответствует поле mm_users, приводит к увеличению счетчика mm_count на единицу. В предыдущем примере значение поля mm_count равно единице. Когда значение поля mm_users становится равным нулю (т.е. когда два потока завершатся), только тогда значение поля mm_count уменьшается на единицу. Когда значение поля mm_count становится равным нулю, то на соответствующую структуру mm_struct больше нет ссылок, и она освобождается, Поддержка двух счетчиков позволяет ядру отличать главный счетчик использования (mm_count) от количества процессов, которые используют данную структуру (mm_users).

Поля mmap и mm_rb — это два различных контейнера данных, которые содержат одну и ту же информацию: информацию обо всех областях памяти в соответствующем адресном пространстве. В первом контейнере эта информация хранится в виде связанного списка, а во втором — в виде красно-черного бинарного дерева. Поскольку красно-черное дерево — это разновидность бинарного дерева, то, как и для всех типов бинарного дерева, количество операций поиска заданного элемента в нем равно О(log(n)). Более детальное рассмотрение красно-черных деревьев найдете в разделе "Списки и деревья областей памяти".

Хотя обычно в ядре избегают избыточности, связанной с введением нескольких структур для хранения одних и тех же данных, тем не менее в данном случае эта избыточность очень кстати. Контейнер mmap — это связанный список, который позволяет очень быстро проходить по всем элементам. С другой стороны, контейнер mm_rb — это красно-черное дерево, которое очень хорошо подходит для поиска заданного элемента. Области памяти будут рассмотрены в этой главе несколько ниже,

Все структуры mm_struct объединены в двухсвязный список с помощью нолей mmlist. Первым элементом этого списка является дескриптор памяти init_mm, который является дескриптором памяти процесса init. Этот список защищен от конкурентного доступа с помощью блокировки mmlist_lock, которая определена в файле kernel/fork.с. Общее количество дескрипторов памяти хранится в глобальной целочисленной переменной mmlist_nr, которая определена в том же файле.

Оглавление книги


Генерация: 0.805. Запросов К БД/Cache: 3 / 0
поделиться
Вверх Вниз