Доступ к панели памяти PCI с низкой задержкой (Linux)

Фон:

У меня есть карта PCI, которая в основном представляет собой часы. Он получает время по GPS и сохраняет текущее время в определенном регистре.

Цель:

Я хочу снова и снова считывать ограниченное количество регистров / байтов (например, текущее время) с минимально возможной задержкой. (Часы обеспечивают очень высокую точность, и я думаю, что потеряю точность, чем выше будет задержка.) Операционная система - RedHat. Язык программирования - C / C ++. Я также хочу записывать в память устройства, поэтому задержка не является проблемой.

Возможные пути:

Я вижу эти пути. Если вы увидите другой, скажите, пожалуйста:

  1. Написание драйвера модуля ядра Linux, который создает символьное устройство (или одно символьное устройство для чтения каждого регистра). Затем приложение пользовательского пространства может выполнить «чтение» файлов / dev /.
  2. DMA
  3. mmap файл sysfs resourceX в пользовательское пространство приложением пользовательского пространства (системный вызов). (например, здесь)
  4. Напишите драйвер модуля ядра Linux, который реализует операцию с файлом mmap.

Вопросов:

  1. Каким образом достигается наименьшая задержка при фактическом чтении регистра? Я знаю, что mmap вызывает много накладных расходов в ядре, но насколько я понимаю, это только для инициализации.
  2. Является ли путь 3 законным? Для меня это похоже на взлом. Как я могу автоматически определить путь / sys / из приложения?
  3. Есть ли разница между путями 3 и 4? Я новичок в программировании драйверов PCI и думаю, что не совсем понимал, как работает способ 4. Я прочитал это (и другие главы эту книгу), но, может быть, вы дадите мне подсказку или пример. Я был бы признателен, что.

person kiigass    schedule 14.07.2018    source источник
comment
В Linux есть механизм VDSO, одна из целей которого - обеспечить самый быстрый способ gettimeofday(). Если ваш драйвер часов может обновлять переменную внутри VDSO, это будет самый быстрый способ.   -  person 0andriy    schedule 19.07.2018


Ответы (2)


Метод 3 или 4 должен работать нормально. По задержке между ними нет никакой разницы. Задержка будет порядка 100 нс.

Метод 4 может потребоваться, если вам нужно инициализировать устройство, или контролировать, каким приложениям разрешен доступ к нему, или принудительно использовать одно считывающее устройство за раз и т. Д. Метод 3 действительно кажется чем-то вроде взлома, потому что он все это пропускает. Но проще, если такие вещи не нужны.

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

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

person prl    schedule 14.07.2018
comment
Я не отвечал на вторую часть вопроса 2. Возможно, кто-то еще может помочь с этим. - person prl; 14.07.2018
comment
Спасибо за Ваш ответ. Ваше последнее предложение: Кроме того, этот метод генерирует много бесполезного трафика DMA, поскольку ЦП считывает значение гораздо реже, чем оно записано. Просто чтобы быть уверенным, что я правильно понял: трафик вызван записью устройства, и большая его часть бесполезна, потому что ЦП считывает только некоторые из этих записей. Верный? У вас есть подсказка или пример, как реализовать способ 4? Я не нашел ничего, что помогло бы мне понять. - person kiigass; 15.07.2018
comment
Я бы начал с той же книги, которую вы связали; это то, что я использовал в прошлом. - person prl; 15.07.2018

Добавление к ответу @prl ...

Метод 3 кажется мне совершенно законным. Вот для чего это нужно. Вы можете посмотреть файл документации ядра: https://www.kernel.org/doc/Documentation/filesystems/sysfs-pci.txt

Вы также можете использовать /sys файловую систему, чтобы найти свое устройство. Сначала запишите идентификатор поставщика и идентификатор устройства для вашей карты часов (и поставщика / устройства подсистемы, если необходимо), затем вы можете легко пройти по /sys/devices иерархии в поисках подходящего устройства (используя специальные файлы vendor, device и т. Д.). Как только вы его нашли, вы, вероятно, знаете, какой resourceN файл открыть из таблицы данных устройства, затем mmap его с соответствующим смещением, и все готово.

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

Основное отличие от метода 4 состоит в том, что драйвер, управляющий устройством, обеспечивает поддержку, позволяющую явно mmap задавать область. Для приложения пользовательского пространства между двумя методами нет большой разницы, кроме имени используемого устройства. Для метода 4 драйвер, вероятно, предоставит символическое имя устройства /dev/clock0 или что-то в этом роде для использования приложением пользовательского пространства (и, предположительно, тогда приложению не нужно искать устройство, оно просто знает имя файла устройства, который нужно открыть).

Из пользовательского пространства вы будете выполнять операцию mmap практически одинаково с любым методом. В методе 4 драйвер внутренне предоставляет физический адрес для сопоставления - и, возможно, смещение - вместо того, чтобы делать это общей подсистемой PCI, но в любом случае это просто open + mmap.

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

person Gil Hamilton    schedule 16.07.2018