Вход/Регистрация
Разработка ядра Linux
вернуться

Лав Роберт

Шрифт:

вывода, используемый по умолчанию */

};

Поле

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
, которая определена в том же файле.

Выделение дескриптора памяти

Указатель на дескриптор памяти, выделенный для какой-либо задачи, хранится в поле

mm
дескриптора процесса этой задачи. Следовательно, выражение
current->mm
позволяет получить дескриптор памяти текущего процесса. Функция
copy_mm
используется для копирования дескриптора родительского процесса в дескриптор порожденного процесса во время выполнения вызова
fork
. Структура
mm_struct
выделяется из слябового кэша
mm_cachep
с помощью макроса
allocate_mm
. Это реализовано в файле
kernel/fork.c
. Обычно каждый процесс получает уникальный экземпляр структуры
mm_struct
и соответственно уникальное адресное пространство.

Процесс может использовать одно и то же адресное пространство совместно со своими порожденными процессами, путем указания флага

CLONE_VM
при выполнении вызова
clone
. Такие процессы называются потоками. Вспомните из материала главы 3, "Управление процессами", что в операционной системе Linux в этом и состоит единственное существенное отличие между обычными процессами и потоками. Ядро Linux больше никаким другим образом их не различает. Потоки с точки зрения ядра — это обычные процессы, которые просто совместно используют некоторые общие ресурсы.

В случае, когда указан флаг

CLONE_VM
, макрос
allocate_mm
не вызывается, а в поле mm дескриптора порожденного процесса записывается значение указателя на дескриптор памяти родительского процесса. Это реализовано с. помощью следующего оператора ветвления в функции
сору_mm
.

if (clone_flags & CLONE_VM) {

 /*

 * current — это родительский процесс

 * tsk — это процесс, порожденный в вызове fork

 */

 atomic_inc(&current->mm->mm_users);

 tsk->mm = current->mm;

}

Удаление дескриптора памяти

Когда процесс, связанный с определенным адресным пространством, завершается, то вызывается функция

exit_mm
. Эта функция выполняет некоторые служебные действия и обновляет некоторую статистическую информацию. Далее вызывается функция
mput
, которая уменьшает на единицу значение счетчика количества пользователей
mm_users
для дескриптора памяти. Когда значение счетчика количества пользователей становится равным нулю, то вызывается функция
mmdrop
, которая уменьшает значение основного счетчика использования
mm_count
. Когда и этот счетчик использования наконец достигает нулевого значения, то вызывается функция
free_mm
, которая возвращает экземпляр структуры
mm_struct
в слябовый кэш
mm_cachep
с помощью вызова функции
kmem_cache_free
, поскольку дескриптор памяти больше не используется.

Структура

mm_struct
и потоки пространства ядра

Потоки пространства ядра не имеют своего адресного пространства процесса и, следовательно, связанного с ним дескриптора памяти. Значение поля

mm
для потока пространства ядра равно
NULL
. Еще одно определение потока ядра — это процесс, который не имеет пользовательского контекста.

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

  • Читать дальше
  • 1
  • ...
  • 131
  • 132
  • 133
  • 134
  • 135
  • 136
  • 137
  • 138
  • 139
  • 140
  • 141
  • ...

Ебукер (ebooker) – онлайн-библиотека на русском языке. Книги доступны онлайн, без утомительной регистрации. Огромный выбор и удобный дизайн, позволяющий читать без проблем. Добавляйте сайт в закладки! Все произведения загружаются пользователями: если считаете, что ваши авторские права нарушены – используйте форму обратной связи.

Полезные ссылки

  • Моя полка

Контакты

  • chitat.ebooker@gmail.com

Подпишитесь на рассылку: