两个相互依赖的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 | +---------------------+
也就是说:设备驱动程序使用“ router.ko”内核模块与其硬件进行通信,该内核模块又是在标准Linux USB驱动程序内核上构建的.
我的问题是,对于Linux PC,只有一个物理设备:通过USB连接的“路由器”硬件,这意味着设备驱动程序成为某种虚拟设备.
我可以将设备驱动程序和路由器设备驱动程序编译到一个大内核模块中,但这似乎不是最佳解决方案.
同样,由于“设备A”先前已直接连接到Linux PC,因此已经存在用于它的驱动程序,该驱动程序具有定义良好的用户空间接口,因为生产环境中已经有需要与之对话的应用程序,因此必须保留该驱动程序.
我的问题或多或少可以归结为:
在上述硬件情况下,您将如何构建Linux内核模块?
解决方法:
我建议的解决方案没有任何问题,该解决方案有一个与实际硬件对话的router.ko模块,和与router.ko对话的子模块dev_A.ko和dev_B.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,除非您没有提到一些复杂的问题.
标签:kernel,linux-kernel,kernel-module,linux 来源: https://codeday.me/bug/20191208/2087905.html