Обратное отображение
Как было сказано в предыдущем разделе, одной из целей алгоритма утилизации страничных кадров является освобождение совместно используемого страничного кадра. Поэтому у ядра Linux 2.6 есть возможность быстрого поиска всех записей в Таблице Страниц, указывающих на один и тот же страничный кадр. Такая функциональность называется обратным отображением.
Тривиальным решением задачи обратного отображения было бы включение в каждый дескриптор страницы дополнительных полей, которые связали бы воедино все записи Таблицы Страниц, указывающие на страничный кадр, ассоциированный с дескриптором страницы. Однако сопровождение таких списков значительно увеличило бы накладные расходы ядра, и поэтому были предложены более сложные решения. Методика, применяемая в Linux 2.6, называется объектно-базированным обратным отображением. Его суть в. том, что для любой утилизируемой страницы режима пользователя ядро хранит обратные ссылки на все области памяти в системе (объекты”), которые включают в себя эту страницу. Каждый дескриптор области памяти хранит указатель на дескриптор памяти, который, в свою очередь, хранит указатель на Глобальный Каталог Страниц. Следовательно, обратные ссылки позволяют алгоритму утилизации страничных кадров получить все записи Таблицы Страниц, которые ссылаются на данную страницу. Поскольку дескрипторов областей памяти меньше, чем дескрипторов страниц, обновление обратных ссылок на совместно используемые страницы отнимает меньше времени. Посмотрим, как эта схема реализована на практике.
Во-первых, у алгоритма утилизации страничных кадров должен быть способ определять, является ли страница, которую он собирается утилизировать, совместно используемой, и является ли она отображающей или анонимной. Для этого ядро изучает два поля дескриптора страницы — mapcount и mapping.
В поле mapcount хранится количество записей Таблицы Страниц, ссылающихся на данный страничный кадр. Счетчик начинает отсчет с -1, это значение свидетельствует о том, что на страничный кадр не ссылается ни одна запись Таблицы Страниц. Таким образом, если счетчик равен нулю, страница не является совместно используемой, а при положительном значении счетчика она таковой является. Функция page mapcount принимает адрес дескриптора страницы и возвращает значение его счетчика mapcount, увеличенное на единицу (так, например, она возвращает 1 для страницы, не используемой совместно и включенной в адресное пространство какого-то процесса режима пользователя).
Поле mapping дескриптора страницы определяет, является ли страница отображающей или анонимной:
- если поле mapping равно null, значит, страница принадлежит кэшу подкачки
- если поле mapping не равно null, а его младший бит равен 1, значит, страница является анонимной, и поле mapping содержит указатель на дескриптор anon vma
- если поле mapping не равно null, а его младший бит равен 0, значит, страница является отображающей. Поле mapping указывает на объект address space соответствующего файла Каждый объект address space в Linux выровнен в оперативной памяти так, что его начальный линейный адрес кратен четырем. Поэтому младший бит поля mapping может быть использован как флаг, показывающий, содержит ли поле указатель на объект address space или на дескриптор anon vma. Это плохой стиль программирования, но ядро работает с огромным количеством дескрипторов, и эти структуры данных должны иметь как можно меньшие размеры. Функция PageAnonO принимает в качестве параметра адрес дескриптора страницы. Она возвращает 1, если младший бит поля mapping установлен, и
О в противном случае.
Функция try to unmap , принимающая в качестве параметра указатель на дескриптор страницы, пытается очистить все записи в Таблице Страниц, указывающие на страничный кадр, ассоциированный с этим дескриптором. Функция возвращает константу swap success (ноль), если ей удалось удалить ссылки на страничный кадр из всех записей Таблицы Страниц; константу swap again (единицу), если какие-то ссылки удалить не удалось; и константу swap fail (двойку), если возникла ошибка.
Функция довольно короткая:
int try_to_unmap(struct page page)
{
int ret;
if (PageAnon(page))
ret = try_to_unmap_anon(page);
else
ret = try_to_unmap_file (page) ; if (!page_mapped(page)) ret = SWAP_SUCCESS; return ret;
}
Функции try_to_unmap_anon И try to unmap f ile занимаются анонимными и отображающими страницами соответственно. Они будут описаны в последующих разделах.
Предыдущая страница | 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 108 109 110 111 | Следующая страница