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

OSzone.net » Microsoft » Разное » Прочее » Прямой доступ к памяти
Автор: Рассел Хичкок
Иcточник: www.netdocs.ru
Опубликована: 11.05.2011

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

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

Хотя основная идея и основная причина обращения к режиму прямого доступа к памяти довольна проста, операции прямого доступа к памяти могут оказаться довольно сложными. Можно себе представить, что будет происходить, если несколько периферийных устройств попытаются получить доступ к памяти одновременно. Поэтому есть необходимость в DMA-контроллере. DMA-контроллер – это устройство, контролирующее все операции по прямому доступу к памяти.

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

*

Рисунок 1: Взаимодействия при прямом доступе к памяти. С разрешения www.eetimes.com

Взрывной или однотактный

Что случается после получения DMA-контроллером контроля над шиной памяти, зависит от того, какой режим работы установлен для DMA-контроллера. Есть два основных режима для DMA-контроллеров. Первый из них называется «взрывным» (burst). Когда DMA-контроллер работает в этом режиме, он сохраняет контроль над шиной памяти на протяжении всего процесса передачи данных. Отрицательным аспектом работы в таком режиме является то, что ЦП не сможет работать с шиной памяти, пока DMA-контроллер не завершит передачу данных. То есть процессор сможет работать только со своими кэшами первого и второго уровней, но не с чем-либо другим в памяти; очевидно, это ограничвает возможности ЦП на время ожидания процессором завершения операции и возвращения контроля над шиной памяти DMA-контроллером.

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

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

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

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

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

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

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


Ссылка: http://www.oszone.net/15247/