Я планирую написать драйвер linux для некоторого оборудования с отображенной памятью (оно находится в ПЛИС, поэтому я могу при необходимости настроить этот интерфейс с отображенной памятью на обоих концах).
Эта логика ПЛИС генерирует последовательность дейтаграмм, которую я должен обработать и затем передать по каналу Ethernet. В ядре нет причин для обработки или сетевого кода, поэтому я спрашиваю о «лучшем» механизме перемещения блоков данных с аппаратного обеспечения в пользовательское пространство. Самым большим осложнением является то, что обработка в пользовательском пространстве должна быть распределена между несколькими процессами.
Скорость передачи данных не очень высока (до 1 Мбит / с), а интерфейс mmio питается довольно глубоким FIFO (в настоящее время 2 КБ, может быть увеличено до 8 КБ), поэтому я думаю, что процесс пользовательского режима с высоким приоритетом может сохранить до.
Что мне действительно нужно, так это указатель на существующий драйвер с существующим многоадресным пользовательским интерфейсом (и не сложным со многими другими). Но план того, что должно быть сделано, был бы разумной заменой.
Я собрал следующие идеи:
AF_NETLINK: поддерживает многоадресную передачу, позаботится о буферизации для меня. Но API нестабилен, мне нужно определить новый идентификатор сокета, который может конфликтовать с другими встроенными драйверами, а интерфейс пользовательского режима довольно специализирован, я не могу использовать стандартные инструменты, такие как socat
, для тестирования потока данных. .
Передача сокета в режиме дейтаграммы или дескриптора файла FIFO из пользовательского пространства и запись в него (как?). Есть многоадресное исправление сокета датаграммы домена unix, которое я мог бы применить.
Предоставление устройства символьного режима одному высокоприоритетному приложению пользовательского режима, которое действует как сервер сокетов дейтаграмм unix-домена и копирует дейтаграммы в каждый подключенный узел. Сохраняются ли границы дейтаграмм для устройств символьного режима (т. Е. Если моя функция драйвера read
возвращает меньше байтов, чем размер буфера fread
, fread
будет возвращать этот блок данных как единое целое, или он может фрагментировать и повторно собирать блоки? Поможет ли мне использовать read (2)
вместо fread (3)
? Есть ли что-то вроде EMSGSIZE
, которую может использовать функция чтения драйвера, чтобы указать, что датаграмма была усечена, или это доступно только для сокетов?)
Предоставление устройства символьного режима, которое может быть открыто несколькими приложениями пользовательского режима одновременно, и буферизация данных для каждого ядра.
Я склоняюсь к устройству символьного режима с сервером домена Unix, который перенаправляет входящие пакеты. Это избавляет меня от необходимости реализовывать логику буферизации внутри драйвера ядра. Тогда возникает вопрос, как разбудить пользовательский процесс от вызова select
или блокировки чтения при возникновении прерывания. Кажется, что моя функция poll
может прочитать управляющий регистр и вернуть POLLIN|POLLRDNORM
, если данные уже доступны, и снять маску прерывания, если нет. И тогда обработчик прерываний будет использовать wake_up
, чтобы пометить wait_queue
как готовый. read
всегда будет маскировать прерывание.