linux kernel-> userspace многоадресные потоковые дейтаграммы - PullRequest
1 голос
/ 28 апреля 2011

Я планирую написать драйвер 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 всегда будет маскировать прерывание.

Ответы [ 3 ]

2 голосов
/ 28 апреля 2011

Я думаю, что netlink - ваш лучший вариант.Кстати, вы можете рассматривать сокет netlink как обычный сокет и использовать POLL, EPOLL, выбрать для него.

Кроме того, что вы подразумеваете под «API нестабилен»?Netlink используется очень часто, и у него довольно неплохой API.

Вам просто нужно использовать универсальную netlink для отправки (и, возможно, получения) сообщений.Ваша задача становится еще проще, если есть односторонняя связь, то есть из ядра -> пользовательское пространство.

РЕДАКТИРОВАТЬ: Если у вас есть доступ, обратитесь к стр.810 года (глава 12) книги Профессиональная архитектура ядра Linux от Wrox.Насколько я знаю, он имеет (относительно) хорошее описание того, как вы можете использовать netlink для связи с пользовательским пространством.

Единственный недостаток netlink - это скудная документация.В противном случае, это нормально, на мой взгляд.

1 голос
/ 04 мая 2011

С опцией символьного устройства read(2) из пространства пользователя в итоге вызовет функцию read() вашего драйвера (указанную в struct file_operations, в котором вы зарегистрировали свое устройство). Таким образом, ваша реализация зависит от того, поддерживаете ли вы границы дейтаграмм и какие ошибки вы хотите возвращать в различных случаях сбоя.

1 голос
/ 28 апреля 2011

Я думаю, что char драйвер - лучший вариант, потому что вы найдете гораздо больше документации для него, а часть ядра проще.API хорошо известен, и вы найдете больше людей с опытом работы с драйвером символов.

Начните с малого, т. Е. С работающей блокировкой на основе прерываний, прочитайте:

  • , если данных нет, спать в очереди
  • иначе вернуть доступные данные в пользовательское пространство.

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

...