Как правило, операция DMA относится только к устройству, а не к процессору, обращающемуся к памяти. На x86 нет отдельных адресных пространств MMIO и RAM - все унифицировано. Некоторые примеры типичных операций DMA:
- Сетевая карта может получить пакет из сети и использовать DMA для записи содержимого пакета в оперативную память системы.
- Контроллер SATA может получить команду записи и использовать DMA для чтения данных для отправки на жесткий диск из системной памяти.
- Видеокарта может использовать DMA для считывания данных текстуры из системной памяти в свою собственную видеопамять. Видеопамять видима для системного процессора через PCI-бар (MMIO), но здесь это не совсем актуально.
Тип dma_addr_t
содержит «шинный адрес» в Linux. Адрес, который, например, устройство PCI (например, контроллер NIC / SATA / GPU) видит в определенной части отображаемой памяти, может отличаться от адреса, используемого ЦП. Таким образом, в Linux есть абстракция «DMA mapping» для обработки этой разницы.
В первом примере, приведенном выше, сетевой стек выделяет буфер в ОЗУ, а затем передает его в функцию dma_map
, чтобы получить адрес шины, который он передает NIC. Сетевая карта будет использовать этот адрес для записи пакета в память.
В более старых системах x86 не было никакой разницы между физическим адресом, который использовал процессор, и адресом шины, который использовали внешние устройства, и функции dma_map
были в значительной степени NOP. Однако в современных технологиях, таких как VT-d, адрес шины, используемый устройством PCI, может полностью отличаться от физического адреса ЦП, поэтому важно выполнить сопоставление DMA и использовать dma_addr_t
для всех используемых адресов. внешними устройствами DMA.