Структура двух взаимозависимых модулей ядра Linux? - PullRequest
3 голосов
/ 06 сентября 2011

В проекте, в котором я участвую, у нас есть следующие настройки оборудования:

     Linux PC ------> "Router" +----> "Device A"
                               |
                               +----> "Device B"

Linux PC - это стандартный ПК X86.

"Маршрутизатор " - это разработанное нами оборудование, которое подключено к другим аппаратным средствам в нашей системе.В этом примере «Устройство A».«Маршрутизатор» подключен к ПК с Linux через USB.

«Устройство A» и «Устройство B» представляют собой аппаратные компоненты системы.Они подключены к оборудованию «Маршрутизатор» через некоторый канал связи (в данном случае это неважно).

Моя задача - написать драйвер устройства Linux для «Устройства А» (а также других устройств).

Я уже создал USB-драйвер общего назначения, который взаимодействует с «Маршрутизатором», и это прекрасно работает.Мой план состоял в том, чтобы иметь стек драйверов, который бы выглядел так:

+----------+----------+
| dev_A.ko | dev_B.ko |
+----------+----------+
|     router.ko       |
+---------------------+
|   Linux USB driver  |
+---------------------+

То есть: драйверы устройств взаимодействуют со своим оборудованием с помощью модуля ядра router.ko, который, в свою очередь, построен на стандартномЯдро драйвера USB для Linux.

Моя проблема в том, что к ПК с Linux существует только одно физическое устройство: аппаратное обеспечение «Маршрутизатор», подключенное через USB, что означает, что драйверы устройств становятся своего рода виртуальными устройствами.

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

Кроме того, поскольку «Устройство A» ранее было подключено напрямую кдля ПК с Linux уже существует драйвер для него с четко определенным пользовательским интерфейсом, который необходимо сохранить, так как в работе уже есть приложения, которым нужно обращаться к нему.

Мой вопрос более или менее сводится к этому:

Учитывая вышеизложенный аппаратный сценарий, как бы вы структурировали модули ядра Linux?

1 Ответ

3 голосов
/ 27 сентября 2011

Я не вижу проблем с вашим предлагаемым решением, состоящим в том, чтобы иметь один модуль router.ko, который взаимодействует с реальным оборудованием, и субмодули dev_A.ko и dev_B.ko, которые общаются с router.ko. Вам просто нужно, чтобы router.ko экспортировал функцию «my_register_driver», аналогичную существующей функции pci_register_driver. Вы должны передать структуру, которая имеет член "id" и указатель на функцию "add_device"; dev_A.ko передает id = "A" и add_device = dev_A_add, и аналогично для dev_B.ko.

Затем, когда появляется router.ko, он обнаруживает аппаратное обеспечение и создает виртуальные устройства (свою собственную контекстную структуру) для A и B. Затем, когда появляется подмодуль, router.ko просто вызывает соответствующие методы add_device с соответствующим виртуальным устройство. router.ko также должен экспортировать методы, которые модули dev_A и dev_B могут использовать для доступа к базовому оборудованию.

В качестве примера того, что я имею в виду, вы можете взглянуть на модули mlx4_core, mlx4_ib и mlx4_en в исходном ядре (я написал их, поэтому выбираю этот пример :). Идея заключается в том, что есть одно устройство PCI, которое можно использовать как устройство InfiniBand и Ethernet; поэтому mlx4_ib и mlx4_en используют mlx4_core для обнаружения и доступа к базовому устройству PCI. Небольшой фрагмент кода, который используют субдрайверы для запроса, какие устройства существуют, находится в drivers / net / mlx4 / intf.c.

Кроме того, что касается существующего интерфейса пользовательского пространства «Устройство A», это не должно быть проблемой. Вы можете просто реализовать тот же ABI в вашем dev_A.ko, если только вы не упомянули о каких-либо сложностях.

...