两个相互依赖的Linux内核模块的结构?

时间:2011-09-06 09:28:51

标签: linux linux-kernel kernel kernel-module

在我参与的项目中,我们有以下硬件设置:

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

Linux PC 是标准的X86 PC。

“路由器”是我们开发的一块硬件,它连接到我们系统中的其他硬件。在此示例中为“设备A”。 “路由器”使用USB连接到Linux PC。

“设备A”“设备B”是系统中的硬件。它们通过某种通信通道连接到“路由器”硬件(在这种情况下不重要)。

我的任务是为“Device A”(以及后来的其他设备)编写Linux设备驱动程序。

我已经构建了一个与“路由器”对话的通用USB驱动程序,这很好用。我的计划是有一个看起来像这样的驱动程序堆栈:

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

即:设备驱动程序使用“router.ko”内核模块与其硬件进行通信,而内核模块又构建在标准Linux USB驱动程序核心上。

我的问题是,对于Linux PC,只有一个物理设备:通过USB连接的“路由器”硬件,这意味着设备驱动程序成为某种虚拟设备。

我可以将设备驱动程序和路由器设备驱动程序编译成一个大内核模块,但它似乎不是最好的解决方案。

此外,由于“设备A”之前已经直接连接到Linux PC,因此已经存在一个驱动程序,它具有明确定义的用户空间界面,必须保留该界面,因为生产中已经有需要与之对话的应用程序

我的问题或多或少归结为:

鉴于上面的硬件方案,您将如何构建Linux内核模块?

1 个答案:

答案 0 :(得分:3)

我认为您提出的解决方案没有任何问题,即一个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和以太网设备;所以mlx4_ib和mlx4_en都使用mlx4_core来发现和访问底层PCI设备。子驱动程序用来询问存在哪些设备的一小段代码在drivers / net / mlx4 / intf.c中。

另外,就现有的“Device A”用户空间界面而言,这应该不是问题。您可以在dev_A.ko中实现相同的ABI,除非您没有提及某些复杂功能。