Добавил:
Developerrnrn Опубликованный материал нарушает ваши авторские права? Сообщите нам.
Вуз: Предмет: Файл:
ОС Нижний.pdf
Скачиваний:
34
Добавлен:
25.03.2023
Размер:
2.75 Mб
Скачать

Лабораторный практикум по курсу "Операционные системы"

Управление памятью в Linux (ядро 2.4.18)

Описание физической памяти в Linux

Linux доступен для широкого диапазона архитектур, соответственно, в нем используется независимый от архитектуры способ описания памяти. Вначале мы рассмотрим структуры, использующиеся для учета банков памяти, страниц и флагов, которые относятся к управлению виртуальной памятью (ВП).

Первое принципиальное понятие, применяемое в ВП ОС Linux - Неоднородный Доступ к Памяти, Non-Uniform Memory Access (NUMA). В больших машинах память может быть организована в виде банков, доступ к которым занимает различное время в зависимости от "расстояния" до процессора. Например, могут быть банки памяти, назначенные конкретным процессорам, или банк памяти вблизи интерфейсной карты, очень подходящий для организации прямого доступа к нему.

Каждый банк памяти называют узлом (node), и это понятие представлено в Linux`е в виде структуры struct pg_data_t (даже в случае UMA архитектуры). Все узлы системы сохранены в списке с именем pgdat_list, заканчивающемся нулевым указателем. Каждый узел связан со следующим полем pg_data_t->node_next. Для ЭВМ с архитектурой UMA, таких как персональные компьютеры, используется только одна статическая структура pg_data_t, с именем contig_page_data.

Каждый узел делится на множество блоков, называемых зонами, которые представляют собой диапазоны адресов памяти. Зоны описываются структурами типа struct zone_t, и

каждая из них имеет тип - ZONE_DMA, ZONE_NORMAL или ZONE_HIGHMEM. ZONE_DMA - память в районе низких физических адресов, которая может потребоваться некоторым устройствам, способным обращаться только к младшим адресам (например, некоторые устройства с интерфейсом ISA могут работать только с младшими 16 Мб). Память в пределах ZONE_NORMAL может быть непосредственно отображена ядром в верхнюю область линейного виртуального адресного пространства. Необходимо отметить, что множество операций ядра могут работать только используя зону ZONE_NORMAL, соответственно она является критической с точки зрения производительности. ZONE_HIGHMEM – остальная часть памяти. На архитектуре x86 зоны распределены следующим образом:

ZONE_DMA

- первые 16MiB памяти

ZONE_NORMAL

- 16MiB - 896MiB

ZONE_HIGHMEM

- 896 MiB - Конец

Каждая физическая страница представлена структурой struct page, и все эти структуры сохранены в глобальном массиве mem_map, которое обычно хранится в начале зоны ZONE_NORMAL или сразу после области, зарезервированной для загружаемого образа ядра, в ЭВМ с малым количеством памяти.

Основные отношения между всеми этими структурами показаны в иллюстрации.

Учебно-исследовательская лаборатория «Информационные технологии» 111

Лабораторный практикум по курсу "Операционные системы"

Рис. 54 Отношения между узлами, зонами и страницами

Поскольку количество памяти, непосредственно доступной ядру (ZONE_NORMAL) ограничено в размере, Linux поддерживает понятие Верхней Области Памяти (High Memory).

Узлы

Как мы упомянули ранее, каждый узел в памяти описан структурой pg_data_t. Назначая страницы, Linux использует локально узловую политику распределения, чтобы выделять память от узла, самого близкого к текущему процессору. Поскольку процессы как правило работают на одном и том же центральном процессоре или могут быть вообще к нему привязаны, в большинстве случаев будет использоваться память непосредственно этого процессора.

struct pglist_data объявлена следующим образом в <linux/mmzone.h>:

129 typedef struct pglist_data { 130 zone_t node_zones[MAX_NR_ZONES];

131 zonelist_t node_zonelists[GFP_ZONEMASK+1];

132 int nr_zones;

133 struct page *node_mem_map;

134 unsigned long *valid_addr_bitmap;

135 struct bootmem_data *bdata;

136 unsigned long node_start_paddr;

137 unsigned long node_start_mapnr;

138 unsigned long node_size;

139 int node_id;

140 struct pglist_data *node_next;

141 } pg_data_t;

Кратко опишем каждое из полей:

112 Учебно-исследовательская лаборатория «Информационные технологии»

Лабораторный практикум по курсу "Операционные системы"

node_zones зоны этого узла: ZONE_HIGHMEM, ZONE_NORMAL, ZONE_DMA;

node_zonelists – предпочтительный порядок использования зон. Обычно неудавшееся выделение в ZONE_HIGHMEM приводит к попытке использования ZONE_NORMAL, в случае неудачи и здесь, используется ZONE_DMA;

nr_zones - число зон в этом узле, от 1 до 3. Не все узлы будут иметь три. Банк центрального процессора, например, может не иметь ZONE_DMA;

node_mem_map – указатель на первую страницу узла в массиве элементов типа struct page, представляющего каждую физическую страницу. Располагается внутри глобального массива mem_map;

valid_addr_bitmap - битовый массив, который описывает "дыры" в узле памяти, для которых не существует физической памяти;

bdata - для менеджера памяти, работающего во время загрузки;

node_start_paddr - стартовый физический адрес узла. Значение, хранящееся здесь –

Page Frame Number (PFN) - определяется как page_phys_addr >> PAGE_SHIFT;

(PAGE_SHIFT = log2PAGE_SIZE)

node_start_mapnr - дает номер первой страницы узла в пределах глобального массива mem_map;

node_size - общее количество страниц в этой зоне; node_id – ID (идентификатор) узла, начинаются с 0;

node_next - указатель на следующий узел в списке, завершающимся нулевым указателем.

Все узлы в системе содержаться в списке, который называется pgdat_list. Вплоть до последних 2.4 ядер (> 2.4.18), блоки программы, обходящие список, выглядели так:

pg_data_t * pgdat; pgdat = pgdat_list; do {

/* do something with pgdata_t */

...

} while ((pgdat = pgdat->node_next));

В более свежих ядрах введен макрос for_each_pgdat(), который тривиально определен как цикл for, чтобы улучшить удобочитаемость кода.

Зоны

Зоны описываются структурой struct zone_t. Она определена следующим образом в

<linux/mmzone.h>:

37 typedef struct zone_struct {

41 spinlock_t lock;

42 unsigned long free_pages;

43 unsigned long pages_min, pages_low, pages_high;

Учебно-исследовательская лаборатория «Информационные технологии» 113

Лабораторный практикум по курсу "Операционные системы"

44 int need_balance;

45

49 free_area_t free_area[MAX_ORDER]; 50

76 wait_queue_head_t * wait_table; 77 unsigned long wait_table_size; 78 unsigned long wait_table_shift; 79

83 struct pglist_data *zone_pgdat;

84 struct page *zone_mem_map;

85 unsigned long zone_start_paddr;

86 unsigned long zone_start_mapnr;

87

91 char *name;

92 unsigned long size;

93 } zone_t;

Кратко опишем каждое из полей: lock - Признак заблокированной зоны.

free_pages - общее количество свободных страниц в зоне;

pages_min, pages_low, pages_high - зональные отметки уровня воды (watermarks),

которые описаны ниже;

need_balance - флаг, говорящий демону выгрузки страниц kswapd о необходимости уравновесить зону;

free_area – битовый массив незанятых страниц;

wait_table – хэш-таблица стоящих в очереди процессов, ожидающих появления свободной страницы. Это важно для функций wait_on_page() и unlock_page();

wait_table_size - размер хэш-таблицы, который является степенью 2;

wait_table_shift - определено как число битов в long минус логарифм по основанию 2 размера хэш-таблицы (предыдущий пункт);

zone_pgdat – указатель на родительский pg_data_t;

zone_mem_map – номер первой страницы зоны в глобальном массиве mem_map; zone_start_paddr - аналогично node_start_paddr; zone_start_mapnr - аналогично node_start_mapnr;

name - название зоны: DMA ("прямой доступ к памяти"), "Normal" ("Нормальный") или "HighMem" (верхняя область памяти);

size - размер зоны в страницах.

114 Учебно-исследовательская лаборатория «Информационные технологии»

Соседние файлы в предмете Современные операционные системы