Отображается ли последний ГБ в адресном пространстве процесса Linux в ту же физическую память?

#linux-kernel #virtual-address-space

#linux-ядро #виртуальное адресное пространство

Вопрос:

Я читал, что первые 3 ГБ зарезервированы для процесса, а последний ГБ — для ядра. Я также читал, что ядро загружается, начиная со 2 МБ физического адресного пространства (в зависимости от конфигурации). Мой вопрос в том, что отображение этого последнего 1 ГБ одинаково для всех процессов и сопоставляется с этой физической областью памяти?

Другой вопрос в том, когда процесс переключается в режим ядра (например, при выполнении системного вызова), тогда какие таблицы страниц используются, таблицы страниц процесса или таблицы страниц ядра? Если используются таблицы страниц ядра, то они не могут получить доступ к ячейкам памяти, принадлежащим процессу. Если это так, то, по-видимому, виртуальная память ядра бесполезна, поскольку весь доступ к коду ядра и данным будет осуществляться через отображение последнего 1 ГБ адресного пространства процесса. Пожалуйста, помогите мне прояснить это (любые полезные ссылки будут высоко оценены)

Ответ №1:

Кажется, вы говорите о 32-разрядных системах x86, верно?

Если я не ошибаюсь, ядро может быть настроено не только на распределение памяти 3 ГБ / 1 ГБ, могут быть и другие варианты (например, 2 ГБ / 2 ГБ). Тем не менее, 3 ГБ / 1 ГБ, вероятно, являются наиболее распространенными в x86-32.

Часть адресного пространства ядра должна быть недоступна из пользовательского пространства. С точки зрения ядра, да, отображение памяти, занимаемой самим ядром, всегда одинаково. Не имеет значения, в контексте какого процесса (или обработчика прерываний, или чего-либо еще) в данный момент работает ядро.

Как одно из следствий, если вы посмотрите на адреса символов ядра в /proc/kallsyms из разных процессов, вы каждый раз увидите одни и те же адреса. И это в точности адреса соответствующих функций ядра, переменных и других с точки зрения ядра.

Итак, я полагаю, ответ на ваш первый вопрос «да», но это, вероятно, не очень полезно для кода пользовательского пространства, поскольку память пространства ядра в любом случае не доступна напрямую оттуда.

Что касается второго вопроса, ну, если ядро в настоящее время работает в контексте какого-либо процесса, оно действительно может получить доступ к пользовательской памяти этого процесса. Я не могу описать это подробно, но, вероятно, реализация функций ядра copy_from_user и copy_to_user могла бы дать вам несколько подсказок. Смотрите arch/x86/lib/usercopy_32.c и arch/x86/include/asm/uaccess.h в исходных текстах ядра. Похоже, что на x86-32 доступ к памяти пользовательского пространства осуществляется в этих функциях напрямую, используя сопоставления памяти по умолчанию для текущего контекста процесса. «Волшебные» вещи там связаны только с оптимизацией и проверкой адреса области памяти на правильность.

Ответ №2:

Да, отображение части адресного пространства ядра одинаково во всех процессах. Часть этого сопоставляет ту часть физической памяти, куда загружен образ ядра, но это не основная ее часть — оставшаяся часть используется для сопоставления других местоположений физической памяти для рабочего набора среды выполнения ядра.

Когда процесс переключается в режим ядра, таблицы страниц не изменяются. Часть адресного пространства ядра просто становится доступной, потому что CPL (текущий уровень привилегий) теперь равен нулю.

Комментарии:

1. тогда зачем нужны таблицы страниц ядра?

2. @Naman Mishra: «Таблицами страниц ядра» будет та часть таблиц страниц, которая соответствует верхнему 1 ГБ линейного адресного пространства. Смысл их в том, чтобы эти части (виртуальной) памяти вообще можно было использовать.