2011-09-06 175 views
3

在一个项目中,我参与,我们有以下的硬件设置:两个相互依赖的Linux内核模块的结构?

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

的Linux PC是一个标准的X86 PC。

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

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

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

我已经构建了一个通用的USB驱动程序,谈到“路由器”,这工作正常。我的计划是有一个看起来像这样的驱动程序堆栈:

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

即:设备驱动程序使用而这又是建立在标准的Linux USB的“router.ko”内核模块的硬件进行通信驱动核心。

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

我可以将设备驱动程序和路由器设备驱动程序编译成一个大的内核模块,但它似乎不是最好的解决方案。另外,由于“设备A”先前已经直接连接到Linux PC,因此已经存在用于其的具有明确定义的用户空间接口的驱动程序,该接口必须被保持,因为已经有应用程序在生产中需要对话它。

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

鉴于上述情形的硬件,你将如何构建Linux内核模块?

+0

在USB中'router'是一个USB集线器。您可以让您的路由器看起来像集线器,设备A和设备B看起来像连接到集线器的USB设备? –

+0

或者,也许你想使用USB(不能想到名字)多功能接口。你知道,就像你有一个假装在同一个设备上的CDROM和硬盘驱动器的USB密钥一样。 –

+0

不,''router'可以由于各种原因而不能看起来像USB集线器。实际上,我甚至可能根本无法控制路由器硬件上的USB功能。它可以随时被USB-to-serial芯片代替(将USB串口暴露给linux主机,串口暴露给'router'device)。 –

回答

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中。

此外,就现有的“设备A”用户空间接口而言,这应该不成问题。你可以在你的dev_A.ko中实现相同的ABI,除非有一些你没有提到的复杂功能。

+0

感谢您的建议。目前,我只是把所有东西都砸成了一个内核模块。这不是很好,但我可能没有时间再分开它们。 我会将此标记为已接受的答案,因为即使我没有尝试过,我也可以看到它是如何工作的。 对于有其他想法的人随时添加另一个答案:) –