我在读
Linux内存管理.我知道
The Linux kernel is responsible for creating and maintaining page tables but employs the cpu’s memory management unit (MMU) to translate the virtual memory accesses of a process into corresponding physical memory accesses.
但是,我也知道内核可以使用一些其功能来管理内存,如virt_to_phys(),virt_to_page(),__pa(),…
例:
static inline unsigned long virt_to_phys(volatile void *address) { return __pa(address); }
用于将虚拟地址翻译成物理地址.
我很困惑他们请帮我告诉我MMU的翻译和内核的翻译之间的关系,并区分它们?
谢谢.
解决方法
在具有虚拟内存的系统中,OS内核负责建立物理和虚拟地址之间的映射.
然而,当cpu执行访问存储器的指令时,cpu执行从进程的虚拟地址到指示存储器中实际位置的物理地址的转换.
您提到的功能可以在内核代码中使用,以获得内核代码中使用的一些地址的虚拟到物理地址的翻译.例如对于x86目标,您可以在io.h中看到virt_to_phys上的定义:
/** * 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(地址)的定义,你会看到它最后调用__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直接映射或分配的内核中的内存,它不会将任意物理映射到虚拟地址.该翻译依赖于查找页表映射.
在任一情况下,作为内核一部分在cpu上执行的实际指令仍然依赖于cpu的MMU从其操作的虚拟地址转换为数据实际位于内存中的物理地址.