Dma Для Новичков Или Что Нужно Знать

Всем привет, сегодня мы поговорим о DMA: именно о той технологии, которая помогает вашему компьютеру воспроизводить за вас музыку, выводить изображения на экран, записывать информацию на жесткий диск и при этом давать мизерную нагрузку на центральный процессор.



ДМА, что это? О чем ты говоришь?

DMA, или Direct Memory Access, — это технология прямого доступа к памяти, минуя центральный процессор.

В эпоху 486-х и первых Пентиумов безраздельно господствовала шина ISA, а также метод обмена данными между устройствами — PIO (Programmed Input/Output).

PIO по своей сути прост: чтобы получить данные от устройства, драйвер операционной системы (или прошивка другого устройства) должен был прочитать эти данные из регистров устройства.

Давайте посмотрим на пример:

  • На сетевую карту поступило 1500 байт данных.

  • Сетевая карта инициирует прерывание, чтобы сообщить процессору, что данные необходимо извлечь из устройства, иначе произойдет так называемое переполнение буфера.

  • Операционная система ловит прерывание от контроллера прерываний и отправляет его на обработку драйверу.

  • Драйвер считывает данные из регистров сетевой карты в цикле, побайтно.

В результате, если чтение одного байта занимает около 1 мс процессорного времени, то чтение 1500 байт занимает 1500 мс.

Но это всего лишь один Ethernet-пакет, представьте, сколько пакетов получает сетевая карта, когда вы читаете любимый хабрахабр.

Конечно, в реальности чтение в режиме PIO можно организовать и по 2,4 байта, но потеря производительности все равно будет катастрофической.

Когда объёмы данных, которыми оперирует процессор, стали увеличиваться, стало понятно, что необходимо минимизировать участие процессора в цепочке обмена данными, иначе всё будет сложно.

И тогда технология прямого доступа к памяти нашла активное применение.

Кстати, DMA используется не только для обмена данными между устройством и оперативной памятью, но и между устройствами в системе; Передача DMA возможна между двумя разделами оперативной памяти (правда, этот маневр неприменим к архитектуре x86).

Также в своем процессоре Cell компания IBM использует DMA в качестве основного механизма связи между элементами синергетической обработки (SPE) и центральным процессорным элементом (PPE).

Также каждый SPE и PPE могут обмениваться данными через DMA с оперативной памятью.

На самом деле этот метод является большим преимуществом Cell, поскольку он устраняет проблемы когерентности кэша во время многопроцессорной обработки данных.



И снова теория

Прежде чем мы перейдем к практике, хотелось бы выделить несколько важных аспектов программирования устройств PCI и PCI-E. Я кратко упомянул регистры устройств, но как процессор получает к ним доступ? Как многие из вас знают, в компьютерных технологиях есть такое понятие, как порты ввода-вывода (порты ввода/вывода).

Они предназначены для обмена информацией между центральным процессором и периферийными устройствами, причем доступ к ним возможен с помощью специальных инструкций по сборке – вход/выход. BIOS (или OpenFirmware в системах на базе PPC) на ранних этапах инициализации устройств PCI, а также некоторых других (контроллер Super IO, контроллер устройств PS/2, таймер ACPI и т. д.) назначает собственный диапазон портов ввода-вывода для конкретный контроллер, где и отображаются регистры устройства.

Кроме того, регистры устройства могут быть сопоставлены с ОЗУ (регистры с отображением памяти), то есть с физическим адресным пространством.

Этот метод имеет ряд преимуществ, а именно:

  • Скорость доступа к физической памяти выше, чем к портам ввода-вывода.

  • Порты ввода-вывода могут отображать не более 65535 байт регистров, при этом размер оперативной памяти современных компьютеров во много раз больше.

  • Чтение регистров устройства из ОЗУ проще, чем использование портов ввода-вывода :)
Данные о том, какой диапазон портов ввода-вывода или оперативной памяти назначен устройству, хранятся в конфигурационном пространстве PCI, а именно в регистрах BAR0, BAR1, BAR2, BAR4, BAR5 [1].

Итак, существует два метода переработки DMA: непрерывный DMA и рассеяние/сбор DMA.

Непрерывный прямой доступ к памяти

Этот метод очень прост и сейчас практически устарел, но до сих пор используется для программирования звуковых контроллеров (например, Envy24HT).

Его принцип заключается в следующем:

  • В оперативной памяти выделяется один буфер достаточно большого размера.

  • Физический адрес (точнее адрес на шине раздела памяти, поскольку физический адрес и адрес шины равны в архитектуре x86, но не равны в PPC) этого буфера записывается в регистр устройства.

  • Когда данные поступают на устройство, контроллер устройства инициирует передачу DMA.
  • Когда буфер полностью заполнен, контроллер устройства выдает прерывание, сообщая ЦП, что буфер следует передать операционной системе.

  • Драйвер операционной системы обрабатывает прерывание и передает полученные данные из буфера дальше по стеку устройств операционной системы.

Как видите, все довольно просто, и как только шина ISA обрела поддержку DMA, этот метод нашел очень широкое применение.

Например, драйверы сетевых карт имели два таких буфера DMA: один для приема данных (rx), другой для отправки (tx).



Разброс/сбор DMA

С увеличением скорости Ethernet-адаптеров непрерывный DMA показал свою несогласованность.

В основном из-за того, что требовались довольно большие области памяти, выделить которые порой было невозможно, поскольку в современных системах фрагментация физической памяти достаточно высока.

Во всем виноват механизм виртуальной памяти, без которого мы сегодня не можем жить :) Решение напрашивается само собой: использовать вместо одного большого раздела памяти несколько, но в разных регионах одной памяти.

Возникает вопрос, а как сообщить контроллеру устройства, как инициировать передачу DMA и по какому адресу записывать данные? И тогда нашли решение — использовать дескрипторы для описания каждой такой области в оперативной памяти.

Типичный дескриптор буфера DMA содержит следующие поля:

  1. Адрес раздела ОЗУ (а именно адрес шины), который предназначен для передачи DMA.
  2. Размер описываемого раздела оперативной памяти.

  3. Необязательные флаги и другие конкретные аргументы.

  4. Адрес следующего дескриптора в памяти.

Структура дескрипторов определяется производителем конкретного контроллера устройства и может содержать любые другие поля.

Дескриптор, как и буфер DMA, находится в оперативной памяти.

Алгоритм рассеяния/сбора DMA следующий:

  • Драйвер операционной системы выделяет и инициализирует дескрипторы буфера DMA.
  • Драйвер выделяет буферы DMA (участки оперативной памяти для передачи DMA) и записывает необходимую информацию о них в дескрипторы.

  • Устройство по мере необходимости заполняет буферы DMA, а после заполнения одного или нескольких буферов инициирует прерывание.

  • Драйвер ОС просматривает все дескрипторы буфера DMA, определяет, какие из них были заполнены контроллером устройства, пересылает данные из буфера дальше по стеку устройства и помечает буфер как готовый к передаче DMA.
Порядок, в котором контроллер устройства заполняет буферы DMA, определяется производителем.

Контроллер может писать в первый свободный буфер DMA или просто писать подряд (дескрипторы буфера DMA в этом случае образуют односвязный кольцевой список) во все буферы и т. д.

Останавливаться.

Вот пожалуй и все на сегодня, иначе будет слишком много информации.

В следующей статье я покажу вам, как IOKit работает с уличной магией.

Жду ваших отзывов и дополнений ;)

Ссылки

[1] Спецификация локальной шины PCI Теги: #DMA #PIO #Системное программирование #драйвер #Системное программирование
Вместе с данным постом часто просматривают:

Автор Статьи


Зарегистрирован: 2019-12-10 15:07:06
Баллов опыта: 0
Всего постов на сайте: 0
Всего комментарий на сайте: 0
Dima Manisha

Dima Manisha

Эксперт Wmlog. Профессиональный веб-мастер, SEO-специалист, дизайнер, маркетолог и интернет-предприниматель.