Прямой доступ к памяти

Опубликовано: 21 Марта, 2023

Введение

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

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

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

Для управления операциями прямого доступа к памяти сначала необходимо настроить контроллер прямого доступа к памяти с информацией, относящейся к предстоящей операции. Эта информация включает в себя такие вещи, как адреса источника и получателя, режим и размер передаваемых данных. Затем контроллер прямого доступа к памяти получает информацию о том, что передавать, куда передавать, как это делать и как долго это делать. Зная это, контроллер прямого доступа к памяти может затем запросить управление шиной памяти у ЦП. Когда ЦП готов отказаться от управления шиной памяти, ЦП отправляет одиночное подтверждение в ответ на сигнал запроса контроллера прямого доступа к памяти.

Изображение 19380
Рисунок 1: Взаимодействие с прямым доступом к памяти. Предоставлено www.eetimes.com

Взрыв или одиночный цикл

Что произойдет после того, как DMA-контроллер получит управление шиной памяти, зависит от режима, в котором DMA-контроллер получил указание работать. Существует два основных режима работы DMA-контроллеров. Первый из них называется взрывным. Когда контроллер прямого доступа к памяти работает в пакетном режиме, он сохраняет контроль над шиной памяти на время передачи памяти. Отрицательным аспектом работы в пакетном режиме является то, что ЦП не сможет получить доступ к шине памяти до тех пор, пока контроллер прямого доступа к памяти не завершит передачу памяти. Хотя ЦП сможет получить доступ к своему кешу L1 и L2, он не сможет получить доступ к какой-либо другой памяти; это, очевидно, ограничит то, что ЦП может выполнить, и может привести к тому, что ЦП придется ждать, пока контроллер DMA завершит передачу памяти и передаст управление шиной памяти обратно ЦП.

Чтобы избежать неблагоприятной ситуации, когда ЦП остается ждать завершения передачи памяти, контроллер DMA может работать в другом режиме, называемом однотактным. При работе в однотактном режиме контроллер DMA отказывается от управления шиной памяти после передачи каждого блока памяти. Размер этого блока обычно составляет 256 или 512 байт. Затем это дает ЦП возможность использовать шину памяти для своих целей, не ожидая значительного времени. К сожалению, у прямого доступа к памяти, работающего в однотактном режиме, есть и обратная сторона. Когда контроллер DMA отказывается от управления шиной памяти, он должен затем отправить запрос в ЦП, чтобы восстановить контроль над шиной, а затем должен дождаться сигнала подтверждения от ЦП, прежде чем восстановить управление шиной для другой передачи блока памяти. Таким образом, необходимость многократного повторения последовательности запроса/подтверждения увеличивает общее время, необходимое для завершения передачи памяти.

Режим работы с одним циклом является наиболее часто используемым режимом, хотя большинство контроллеров прямого доступа к памяти могут работать в обоих режимах. Оптимальная длина блока, которую DMA передаст перед отказом от управления шиной и повторным запросом управления, является довольно сложным вопросом. Одним из основных факторов при определении оптимального размера блока является наблюдаемая частота ошибок. Поскольку при передаче памяти наблюдаются ошибки (довольно часто, когда память передается по каналу связи), должна происходить повторная передача данных. По этой причине при высоком уровне ошибок оптимальной является меньшая длина блока. Однако при небольшом количестве ошибок небольшая длина блока приведет к увеличению количества циклов запросов/подтверждений между контроллером DMA и ЦП, что уменьшит общее время передачи памяти. То, как эти решения реализуются, зависит от каждого производителя контроллера прямого доступа к памяти (точнее, от инженера, разработавшего его!) и широко не распространено. Если вы хотите узнать, как это определяется для конкретного контроллера DMA, вы можете найти его где-нибудь в документации, в противном случае может потребоваться запрос в компанию.

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

Когерентность кэша

Другая проблема, которая возникает во время операций прямого доступа к памяти, называется когерентностью кэша. Когда ЦП обращается к ячейке памяти, значение этой ячейки сохраняется в кэш-памяти ЦП. Если операция прямого доступа к памяти задействует это место в памяти, то значение в кэше ЦП может не совпадать со значением в истинном месте в памяти. Чтобы узнать больше о когерентности кеша, просмотрите мою предыдущую статью здесь.

Для решения этой проблемы есть два возможных решения. В системах с полностью когерентным кэшем реализовано аппаратное решение, в котором контроллер прямого доступа к памяти посылает сигнал контроллеру кэша, когда он хочет получить доступ к ячейке памяти. Если DMA захочет записать в это место, контроллер кеша аннулирует значение кеша ЦП. Если DMA хочет прочитать ячейку памяти, контроллер кеша очистит кеш ЦП, чтобы убедиться, что ячейка памяти содержит самое последнее значение (которое будет значением в кеше ЦП). Этот метод работы требует некоторых накладных расходов, но гарантирует согласованность кэш-памяти ЦП.

В системах с неполной когерентностью кэша работа по поддержанию когерентности кэша возложена на операционную систему. Операционная система должна будет решить, следует ли очищать кеш перед операцией прямого доступа к памяти или делать ее недействительной после нее. Какой метод лучше? Я не уверен, что есть окончательный ответ, оба метода адекватны. Однако лично я предпочитаю элегантность аппаратного решения, реализованного в системах с полной когерентностью кэша.