Linux Kernel (Ядро линукса) (часть 1)


Аллокатор зон

Аллокатор зон является, образно говоря, передней частью аллокатора страничных кадров ядра. Этот компонент должен обнаружить зону памяти, содержащую некоторое количество свободных страничных кадров, достаточное для удовлетворения запроса на память. Эта задача не так проста, как может показаться на первый взгляд, потому что перед аллокатором зон стоит ряд целей:
- защищать пул зарезервированных страничных кадров;
- запускать алгоритм утилизации страничных кадров, когда свободной памяти не хватает, а блокирование текущего процесса разрешено; после освобождения нескольких страничных кадров аллокатор зон может повторить попытку выделения памяти;
- по возможности, беречь небольшую и очень ценную зону памяти zone dma; например, аллокатор зон не должен торопиться с выделением страничных кадров в зоне zone dma, если поступил запрос на кадры в зоне zone normal

ИЛИ ZONE_HIGHMEM

Ранее мы видели, что любой запрос на группу смежных страничных кадров, в конечном счете, обрабатывается с помощью макроса aiioc pages. Этот макрос, в свою очередь, вызывает функцию aiioc pages о, являющуюся "сердцем" аллокатора зоны. Она принимает три параметра:
- gfp mask — флаги, заданные в запросе на выделение памяти - order — логарифмический размер группы смежных страничных кадров, подлежащих выделению;
- zoneiist— указатель на структуру zoneiist, описывающую в порядке предпочтения зоны, подходящие для выделения памяти.
Функция aiioc pages просматривает каждую зону памяти, включенную
в структуру zoneiist. Код, выполняющий эту задачу, выглядит примерно так:
for (i = 0; (z=zonelist->zones[i]) != NULL; i++) { if (zone_watermark_ok(z, order, ) ) {
page = buffered_rmqueue(z, order, gfp_mask); if (page)
return page;}}
Для каждой зоны памяти функция сравнивает количество свободных страничных кадров с неким пороговым значением, которое зависит от флагов выделения памяти, от типа текущего процесса и от того, сколько раз функция уже проверяла эту зону. На практике, если наблюдается дефицит свободной памяти, каждая зона обычно сканируется несколько раз, причем с очередным просмотром понижается порог минимального количества свободной памяти, требуемой для выделения. Таким образом, приведенный фрагмент кода повторяется несколько раз (с незначительными вариациями) в теле функции
aiioc pages . Функция buf fered rmqueue уже была описана ранее в этой
главе: она возвращает дескриптор первого выделенного страничного кадра или null, если зона памяти не содержит группу смежных страничных кадров запрошенного размера.

Служебная функция zone_watermark_ok принимает несколько параметров, которые определяют порог min для количества свободных страничных кадров в зоне памяти. В частности, функция возвращает 1, если выполнены следующие два условия:
- Кроме страничных кадров, которые необходимо выделить, в зоне памяти имеется как минимум min свободных страничных кадров, на считая заре
зервированных на случай дефицита памяти (поле lowmem reserve дескриптора зоны).
- Кроме страничных кадров, которые необходимо выделить, имеется как минимум min/2 свободных страничных кадров в блоках порядка не меньше к (для каждого А; от 1 до порядка выделения). Следовательно, если order больше нуля, должно быть, как минимум, min/2 свободных страничных кадров в блоках порядка не меньше 2; если order больше единицы, должно быть как минимум min/4 свободных страничных кадров в блоках порядка не меньше 4 и т. д.

Значение порога min определяется функцией zone watermark ok следующим образом:

- базовое значение передается в качестве параметра функции и может быть равно ОДНОЙ ИЗ отметок В зоне: pages_min, pages low ИЛИ pages high;
- базовое значение делится пополам, если установлен флаг gfp high, переданный в качестве параметра. Как правило, этот флаг установлен, если установлен флаг gfp highmem в поле gfp mask, т. е. если страничные кадры
могут быть выделены в верхней памяти;
- пороговое значение делится еще на четыре, если установлен флаг can try harder, передаваемый в качестве параметра. Этот флаг обычно установлен, либо если установлен флаг gfp wait в поле gfp mask, либо если текущий процесс является процессом реального времени, и выделение памяти происходит в контексте процесса (за пределами обработчиков прерываний и функций отложенного выполнения).
Функция aiioc pages выполняет следующие действия:
1. Производит первое сканирование зон памяти (фрагмент кода, приведенный ранее). По ходу этого первого сканирования значение порога min устанавливается равным z->pages_iow, где z указывает на дескриптор рассматриваемой ЗОНЫ (параметры can try harder И gfp high равны 0).
2. Если функция не завершила работу на предыдущем шаге, значит, свободной памяти осталось не очень много. Функция "будит” потоки ядра kswapd, чтобы начать асинхронную утилизацию страничных кадров.
3. Выполняет второе сканирование зон памяти, передавая в качестве базового значения порога значение z->pages_min. Как было сказано ранее, окончательное значение порога определяется также флагами can try harder и gfp high. Этот шаг практически идентичен шагу , но здесь функция работает с меньшим порогом.
4. Если функция не завершила работу на предыдущем шаге, значит, в системе явный дефицит памяти. Если управляющий тракт, выдавший запрос на
выделение памяти, не является обработчиком прерываний и функцией отложенного выполнения, и он пытается утилизировать страничные кадры (у текущего процесса установлен флаг pf memalloc, либо pf memdie), функция выполняет третье сканирование зон памяти и пытается выделить страничные кадры, игнорируя пороги дефицита памяти, т. е. — не вызывая функцию zone watermark okO. Это единственный случай, когда управляющему тракту ядра разрешено исчерпать резерв страниц, определяемый полем lowmem reserve дескриптора зоны. На самом деле, в этой ситуации управляющий тракт ядра, сделавший запрос на память, в конечном счете, пытается освободить некоторые страничные кадры, чтобы получить запрошенную память, если это вообще возможно. Если ни в одной зоне памяти нет достаточного количества страничных кадров, функция возвращает null, чтобы известить вызывающую функцию о неудаче.
5. Если функция находится на этом шаге, значит, поток ядра не пытается утилизировать память. Если флаг gfp wait в поле gfp mask не установлен, функция возвращает null, чтобы уведомить поток ядра о неудачной попытке выделения памяти. В этой ситуации нет способа удовлетворить запрос, не блокируя текущий процесс.
6. Если функция находится на этом шаге, значит, текущий процесс может быть блокирован. Функция вызывает функцию cond_resched для проверки, не требуется ли процессор какому-нибудь другому процессу.
7. Устанавливает флаг pf memalloc у процесса current, отмечая готовность процесса выполнить утилизацию памяти.
8. Сохраняет в поле current->reciaim_state указатель на структуру reclaim state. Эта структура имеет ТОЛЬКО ОДНО поле, reclaimed_slab, инициализированное нулем (применение этого поля обсуждается далее в этой главе).
9. Вызывает функцию try to free pages для поиска страничных кадров, которые можно утилизировать. Вызванная функция может блокировать текущий процесс. Когда она возвращает управление, функция aiioc pages о сбрасывает флаг pf memalloc процесса current и снова вызывает функцию cond_resched.
10. Если на предыдущем шаге удалось освободить некоторое количество страничных кадров, функция выполняет еще одно сканирование зон памяти, идентичное сканированию на шаге 3. Если запрос на выделение не может быть удовлетворен, функция решает, следует ли ей продолжить сканирование зоны памяти. Если флаг gfp noretry сброшен, и либо запрос на память охватывает до восьми страничных кадров, либо установ-
лен один из флагов gfp repeat или gfp nofail, функция вызывает
функцию bik congestion waitо, чтобы ненадолго задержать процесс, и возвращается к шагу . В противном случае функция возвращает null, чтобы известить вызывающую функцию о неудаче.
11. Если на шаге не был освобожден ни один страничный кадр, ядро стоит перед серьезной проблемой, потому что возник опасный дефицит свободной памяти, а утилизировать страничные кадры не удалось. Настал момент для принятия принципиально важного решения. Если потоку ядра разрешено выполнять операции, зависящие от файловой системы и необходимые ДЛЯ уничтожения процессов (флаг GFP FS В ПОЛе gfp_mask
установлен), а флаг gfp noretry сброшен, функция выполняет следующие действия:
• снова сканирует зоны памяти с пороговым значением z->pages_high;
• вызывает функцию out of memory , чтобы приступить к освобожде- нию памяти путем уничтожения процесса
• возвращается к шагу .
Поскольку отметка уровня, использованная на шаге , значительно выше отметок, использованных при предыдущих сканированиях, весьма вероятно, что этот шаг закончился неудачей. На практике шаг завершается успешно, только если другой поток ядра уже уничтожает процесс, чтобы получить его память. Таким образом, шаг позволяет избежать уничтожения двух ни в чем не повинных процессов, вместо одного.
Освобождение группы страничных кадров
Аллокатор зон занимается также и освобождением страничных кадров. К счастью, освобождение памяти намного проще ее выделения.
Все макросы и функции ядра, освобождающие страничные кадры, опираются в своей работе на функцию free pages . В качестве параметров
она принимает адрес дескриптора первого освобождаемого страничного кадра (раде) и логарифмический размер группы смежных кадров, подлежащей освобождению (order).

Функция выполняет следующие действия:

1. Проверяет, действительно ли первый страничный кадр принадлежит динамической памяти (его флаг PG reserved должен быть сброшен). Если это не так, завершает работу.
2. Уменьшает счетчик обращений page->_count. Если он все еще больше или равен 0, завершает работу.
3. Если значение order равно 0, функция вызывает функцию free_hot_page , чтобы освободить страничный кадр для горячего” кэша процессора в соответствующей зоне памяти.
4. Если значение order больше 0, функция заносит страничные кадры в локальный СПИСОК И вызывает функцию free_pages_bulk, ЧТОбы освобо- дить их для buddy-системы соответствующей зоны.

Предыдущая страница | 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 103 104 105 106 107 | Следующая страница




Возможно, Вас также заинтересует:

ОС Knoppix - это Linux без про...

ВведениеЕсли вы цените свое время, умеете считать деньги и знаете стоимость информации, то эта книга...

Linux Kernel (Ядро линукса) (ч...

Спин-блокировкаСпин-блокировка необходима в многопроцессорной системе, потому что могут возникнуть...

Linux Kernel (Ядро линукса) (ч...

Копирование при записи В системах Unix первых поколений создание процесса было реализовано довольно...

Linux Kernel (Ядро линукса) (ч...

Буферы блоков и головы буферовУ каждого буфера есть дескриптор голова буфера, имеющий тип buffer...