Какова связь между virt_to_phys и процессором MMU в ядре Linux?
Я читаю об управлении памятью Linux. Я знаю, что
Ядро Linux отвечает за создание и поддержку таблиц страниц, но использует модуль управления памятью процессора (MMU), чтобы перевести обращения виртуальной памяти к процессу в соответствующие обращения к физической памяти.
Но я также знаю, что ядро может использовать некоторые свои функции для управления памятью, например virt_to_phys()
, virt_to_page()
, __pa()
,...
Пример:
static inline unsigned long virt_to_phys(volatile void *address)
{
return __pa(address);
}
используется для перевода виртуального адреса на физический адрес.
Я очень смущен ими. Пожалуйста, помогите мне показать отношения между переводом MMU и переводом ядра и отличить их?
Ответы
Ответ 1
В системах с виртуальной памятью ядро ОС отвечает за установление сопоставления между физическими и виртуальными адресами.
Однако, когда ЦП выполняет инструкции, которые обращаются к памяти, ЦП выполняет перевод с виртуального адреса процесса на физический адрес, который указывает фактическое местоположение в памяти.
Указанные выше функции могут использоваться внутри кода ядра, чтобы получить перевод виртуальных физических адресов для некоторых адресов, которые используются в коде ядра. Например, для цели x86 вы можете определить определение virt_to_phys
в io.h:
/**
* virt_to_phys - map virtual addresses to physical
* @address: address to remap
*
* The returned physical address is the physical (CPU) mapping for
* the memory address given. It is only valid to use this function on
* addresses directly mapped or allocated via kmalloc.
*
* This function does not give bus mappings for DMA transfers. In
* almost all conceivable cases a device driver should not be using
* this function
*/
static inline phys_addr_t virt_to_phys(volatile void *address)
{
return __pa(address);
}
и если вы выполните определение __pa(address)
, вы увидите, что он вызывает вызов __phys_addr
, который определяется как:
unsigned long __phys_addr(unsigned long x)
{
if (x >= __START_KERNEL_map) {
x -= __START_KERNEL_map;
VIRTUAL_BUG_ON(x >= KERNEL_IMAGE_SIZE);
x += phys_base;
} else {
VIRTUAL_BUG_ON(x < PAGE_OFFSET);
x -= PAGE_OFFSET;
VIRTUAL_BUG_ON(!phys_addr_valid(x));
}
return x;
}
Итак, вы можете видеть, что ядро вычисляет физический адрес с виртуального адреса с помощью смещения. В зависимости от архитектуры, которую код скомпилирован для перевода, будет отличаться. И, как упоминается комментарий для virt_to_phys
, это работает только для памяти в ядре, которое непосредственно отображается или распределяется через kmalloc, оно не переводит произвольные физические на виртуальные адреса. Этот перевод зависит от поиска отображения таблицы страниц.
В любом случае фактические инструкции, выполняемые на процессоре как часть ядра, будут по-прежнему полагаться на процессор MMU процессора для перевода с виртуальных адресов, на которых они работают, на физические адреса, где данные фактически находятся в памяти.
Ответ 2
Вы можете прочитать "Понимание книги ядра Linux", чтобы получить дополнительную информацию.
Ответ 3
По моему мнению, любое использование физического адреса на стороне ядра просто для справки и, скорее всего, просто будет переведено для любых реальных изменений/ходов. Для этого существует ряд причин: одна из них заключается в том, что память может быть переназначена для другой цели, IE перемещает данные из физической памяти в файл страницы (на диске) или перемещается в пределах выделения физической памяти, если больше места для этих данных. Таким образом, было бы нецелесообразно использовать физический адрес, если ядро будет просто перемещать его, не сообщая вам.
Вот интересный бит на эту тему.
И гораздо подробнее здесь.
Ответ 4
Virt_to_phys() и другие на самом деле используют разные атрибуты таблиц страниц, такие как PAGE_OFFSET и т.д. Эти таблицы страниц создаются подсистемой управления памятью ядра, но они в свою очередь используют оборудование MMU для чтения/записи физическая страница в основной памяти.
Вы также можете ссылаться на различные доступные документы: один из них:
https://www.kernel.org/doc/gorman/html/understand/understand006.html
Ответ 5
Вот точки.
1.) Ядро и другие мягкие работы с точки зрения виртуальных адресов. Каждый раз для поиска подходящего поиска таблицы аппаратных страниц аппаратного обеспечения (или выборки TLB) необходимо.
2.) В момент загрузки ядро устанавливает виртуальное отображение: для простоты я скажу, что он отображает память по адресам 0x0.. n в 0xc0000000.. 0xc0000000 + n (так называемая низкая память).
3.) Установленное отображение является статическим. Для адресов lowmem подходят следующие функции:
virt_to_page(), __pa(), ...
Это означает, что
virtual address = physical address + some offset
Таким образом, вы можете легко получить адрес phys/virt для соответствующей страницы lowmem в коде ядра (MMU использует универсальные механизмы, т.е. ежедневную таблицу страниц). Это смещение - это просто соглашение, не более того.
Ответ 6
Трансляция адресов MMU - это аппаратное (процессорное) поведение. Перевод должен быть выполнен, так как физический адрес является допустимым адресом, который может использоваться аппаратным обеспечением для доступа к памяти. С другой стороны, функция ядра, такая как va_to_pa()
, используется для преобразования логического адреса ядра (va) в физический адрес (pa), что означает, что ядро использует виртуальный адрес, отличный от физического адреса, хотя это просто постоянный сдвиг между va и pa.
Инструкции и данные ядра находятся в виртуальном адресе, но ядро использует физический адрес для выполнения многих задач, таких как подготовка записи в таблице страниц, получение адреса dma для устройства и скоро. Поэтому для ядра нужны функции типа va_to_pa()
.