物理地址,设备地址和虚拟地址之间的差异

时间:2014-07-23 07:03:10

标签: android linux-kernel kernel kernel-module

设备地址物理地址虚拟地址之间有什么区别?

实际上我在驱动程序中尝试mmap,我坚持这个概念。

1 个答案:

答案 0 :(得分:7)

documentation说:

  

内核通常使用虚拟地址。返回的任何地址   kmalloc(),vmalloc()和类似的接口是一个虚拟地址,可以   存储在" void *"。

中      

虚拟内存系统(TLB,页表等)转换虚拟   地址到CPU物理地址,存储为" phys_addr_t"要么   " resource_size_t&#34 ;.内核像寄存器一样管理设备资源   物理地址。这些是/ proc / iomem中的地址。身体上的   地址对驱动程序没有直接用处;它必须使用ioremap()来映射   空间并产生一个虚拟地址。

     

I / O设备使用第三种地址:"总线地址"或" DMA地址"。   如果器件在MMIO地址处有寄存器,或者它执行DMA读取   或写入系统存储器,设备使用的地址是总线地址。   在某些系统中,总线地址与CPU物理地址相同,但是   一般来说,他们不是。 IOMMU和主桥可以产生任意性   物理地址和总线地址之间的映射。

     

这是一张图片和一些例子:

             CPU                  CPU                  Bus
           Virtual              Physical             Address
           Address              Address               Space
            Space                Space

          +-------+             +------+             +------+
          |       |             |MMIO  |   Offset    |      |
          |       |  Virtual    |Space |   applied   |      |
        C +-------+ --------> B +------+ ----------> +------+ A
          |       |  mapping    |      |   by host   |      |
+-----+   |       |             |      |   bridge    |      |   +--------+
|     |   |       |             +------+             |      |   |        |
| CPU |   |       |             | RAM  |             |      |   | Device |
|     |   |       |             |      |             |      |   |        |
+-----+   +-------+             +------+             +------+   +--------+
          |       |  Virtual    |Buffer|   Mapping   |      |
        X +-------+ --------> Y +------+ <---------- +------+ Z
          |       |  mapping    | RAM  |   by IOMMU
          |       |             |      |
          |       |             |      |
          +-------+             +------+
     

在枚举过程中,内核会了解I / O设备和   他们的MMIO空间和将它们连接到系统的主桥。对于   例如,如果PCI设备有BAR,则内核读取总线地址(A)   从BAR转换为CPU物理地址(B)。地址B.   存储在struct资源中,通常通过/ proc / iomem公开。当一个   驱动程序声称一个设备,它通常使用ioremap()来映射物理地址   B在虚拟地址(C)。然后它可以使用例如ioread32(C)来访问   器件在总线地址A处注册。

     

如果设备支持DMA,则驱动程序使用kmalloc()或设置缓冲区   一个类似的接口,它返回一个虚拟地址(X)。虚拟   存储器系统将X映射到系统RAM中的物理地址(Y)。司机   可以使用虚拟地址X来访问缓冲区,但设备本身   不能,因为DMA没有通过CPU虚拟内存系统。

     

在一些简单的系统中,设备可以直接对物理地址执行DMA   是的。但在许多其他方面,有IOMMU硬件可以转换总线   地址到物理地址,例如,它将Z转换为Y.这是一部分   DMA API的原因:驱动程序可以给出虚拟地址X.   像dma_map_single()这样的接口,用于设置任何所需的IOMMU   映射并返回总线地址Z.然后驱动程序告诉设备   执行DMA到Z,IOMMU将它映射到系统中地址Y的缓冲区   RAM。