#linux-kernel #virtual-memory
#linux-ядро #виртуальная память
Вопрос:
Я пытаюсь сделать управление памятью Linux немного более понятным для целей настройки и производительности.
Читая эту очень интересную redbook «Рекомендации по производительности и настройке Linux», найденную на веб-сайте IBM, я наткнулся на то, что я не до конца понимаю.
На 32-разрядных архитектурах, таких как IA-32, ядро Linux может напрямую обращаться только к первому гигабайту физической памяти (896 МБ с учетом зарезервированного диапазона). Память выше так называемой
ZONE_NORMAL
должна быть отображена в нижний 1 ГБ. Это сопоставление полностью прозрачно для приложений, но выделение страницы памяти вZONE_HIGHMEM
вызывает небольшое снижение производительности.
- почему память выше 896 МБ должна быть отображена в меньший 1 ГБ?
- Почему выделение страницы памяти в
ZONE_HIGHMEM
влияет на производительность? - для чего тогда используется
ZONE_HIGHMEM
? - почему ядро, способное распознавать до 4 ГБ (
CONFIG_HIGHMEM=y
), может использовать только первый гигабайт?
Заранее спасибо
Ответ №1:
Когда пользовательский процесс подключается к ядру, таблицы страниц не изменяются. Это означает, что одно линейное адресное пространство должно быть способно охватывать как адреса памяти, доступные пользовательскому процессу, так и адреса памяти, доступные ядру.
В IA-32, который допускает линейное адресное пространство объемом 4 ГБ, обычно первые 3 ГБ линейного адресного пространства выделяются пользовательскому процессу, а последний 1 ГБ линейного адресного пространства выделяется ядру.
Ядро должно использовать свой диапазон адресов в 1 ГБ, чтобы иметь возможность обращаться к любой части физической памяти, которая ему необходима. Память выше 896 МБ не «отображается в младший 1 ГБ» — происходит то, что физической памяти ниже 896 МБ присваивается постоянный линейный адрес в части ядра линейного адресного пространства, тогда как памяти выше этого предела должно быть назначено временное отображение в оставшейся части линейного адресного пространства.
Отображение ZONE_HIGHMEM
страницы в пользовательский процесс не влияет на производительность — для пользовательского процесса все страницы физической памяти равны. Влияние на производительность возникает, когда ядру требуется получить доступ к странице, не являющейся пользовательской, в ZONE_HIGHMEM
— для этого оно должно отобразить ее в линейное адресное пространство, если оно еще не отображено.
Комментарии:
1. «В IA-32, который допускает линейное адресное пространство объемом 4 ГБ, обычно первые 3 ГБ линейного адресного пространства выделяются пользовательскому процессу, а последний 1 ГБ линейного адресного пространства выделяется ядру». Как это обычная схема распределения? Могу ли я выделить 2 ГБ пространства пользовательскому процессу и 2 ГБ ядру? И как?
2. @yegle: Вы можете изменить разделение пользователя и ядра во время сборки ядра. Вы, должно быть, ответили
Y
наEXPERIMENTAL
вариант, после чего вы увидите выбор разделения пользователя / ядра (по умолчанию 3 ГБ / 1 ГБ, а также 2 ГБ / 2 ГБ и 1 ГБ / 3 ГБ).3. @caf, у меня есть два вопроса. Q1: Когда происходит сбой, таблицы страниц не изменились. Таким образом, в ядре первые 3 ГБ указывают на память пользовательских процессов, а остальные — на ядро. Если это так, нужны ли нам какие-либо дополнительные настройки? Q2: Вы говорите, что «Ядро должно использовать свой диапазон адресов в 1 ГБ, чтобы иметь возможность обращаться к любой части физической памяти, которая ему необходима». Зачем ядру напрямую обращаться к физической памяти, когда есть MMU для преобразования виртуальных адресов в физические адреса?
4. @PaulDC: В качестве примера рассмотрим ядро, выполняющее
read()
запрос пользовательского пространства со страницы pagecache, которая находится вZONE_HIGHMEM
. Для этого она должна быть скопирована со страницы кэша страниц в предоставленный буфер пользовательского пространства, что означает, что она должна иметь возможность обращаться к странице кэша страниц, поэтому она должна быть где-то отображена в адресное пространство ядра.