Существует два типа виртуальных адресов, которые использует ядро Linux:
- То, что вы уже упомянули в строке «Память ядра (виртуальная), напрямую соответствует физической памяти (просто смещение с 0xC000_0000 дастнам физический адрес)Это сопоставляется с непрерывными физическими адресами.
- Использование vmalloc.
Первый выполняется с использованием MACRO:
include/asm-x86/page_32.h
#define __pa(x) ((unsigned long)(x)-PAGE_OFFSET)
#define __va(x) ((void *)((unsigned long)(x)+PAGE_OFFSET))
_pa (x) делает виртуальныйк физическому переводу.Обратите внимание, что этот перевод происходит во встроенном во время компиляции.Перевод таблицы страниц не происходит.Это последнее предложение очень важно.
С другой стороны, используя второй метод, вы можете выделить память, которая является непрерывной в виртуальной памяти, но не может быть таковой в физической памяти.Теперь в этом случае требуется полный перевод таблицы страниц при первом обращении к виртуальному адресу.Вопрос в том, кто это делает?
В случае машин CISC (например, x86) MMU (аппаратное обеспечение) делает это в случае пропуска TLB (первый доступ к виртуальному адресу) и обновляет таблицу страниц.Для виртуальных адресов ядра (полученных через vmalloc) они хранятся в виде записей TLB.Они называются глобальными записями, и когда происходит переключение контекста процесса, они в основном игнорируются и не сбрасываются, как остальные записи пространства процесса-адреса.Однако, когда вы делаете vfree для освобождения связанной виртуальной памяти, эти записи удаляются.
В случае RISC-машины (например, MIPS) перевод страницы обрабатывается программным обеспечением.После пропуска TLB, оборудование вызывает исключение.Дескриптор ловушки выполняется в режиме ядра, чтобы выполнить перевод и обновляет TLB, используя специальные инструкции.После возврата из обработчика ловушек запускается та же строка кода и происходит TLB.
Пожалуйста, обратитесь к: http://pages.cs.wisc.edu/~remzi/OSFEP/vm-tlbs.pdf
Суть в том, что не все адреса ядра отображаютсякак вы описали.В вашем случае физические адреса генерируются во время компиляции.Итак, зачем добавлять запись TLB.Для адресов из vmalloc присутствуют записи TLB.Когда происходит переключение контекста между процессами, нет необходимости сбрасывать весь TLB, и глобальные записи, сделанные ядром vmalloc, могут быть сохранены.Когда вы используете vfree, соответствующие глобальные записи сбрасываются.