将设备驱动程序实现为一组内核模块
我有一个用户空间库,用于通过串行端口与设备进行通信。该库相当复杂,执行许多任务,包括将标头放到有效负载上、对消息进行分段、发送消息、处理响应、初始化设备等...
我想将此库移至内核空间,并正在考虑拆分将该库分成几个定义良好的内核模块,以便
- 我可以在将来交换层(例如用 SPI 层交换 USART 层)。
- 开发会更容易。如果它被分割,我可以将库一块一块地迁移到内核空间。
以前有人做过这样的事情吗?内核模块之间通信的最佳方式(就效率而言)是什么?有什么我应该避免的陷阱吗?
最后,是否有任何作为一组内核模块实现的驱动程序的好示例?
I have a user-space library that is used to communicate to a device over a serial port. The library is fairly complex and performs many tasks including putting headers onto payloads, fragmenting the messages, sending messages, processing responses, initializing the device, etc...
I'd like to move this library to kernel-space and am considering breaking up the library into several well-defined kernel modules so that
- I can leave the door open to swap out layers in the future (for example swapping out the USART layer with an SPI layer).
- Development will be easier. If it were divided up, I could migrate the library to kernel-space piece-by-piece.
Has anyone ever done something like this before? What are the best ways (in terms of efficiency) to communicate between kernel modules? Are there any pitfalls I should avoid?
Finally, are there any good examples of drivers that are implemented as a set of kernel modules?
如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。
绑定邮箱获取回复消息
由于您还没有绑定你的真实邮箱,如果其他用户或者作者回复了您的评论,将不能在第一时间通知您!
发布评论
评论(2)
不确定这是否有帮助,但 ALSA 由每个不同声音芯片的许多不同模块组成,以及其他模块所依赖的几个常见模块:
重建依赖关系图留给读者作为练习。
Not sure if this helps, but ALSA consists of many distinct modules for each different sound chip, and several common ones that the others depend on:
Reconstructing the dependency graph is left as an exercise to the reader.
所有内核模块都在同一地址空间中运行。要从一个模块调用另一个模块,您需要导出一些符号:函数或全局变量。尽管在这种情况下使用全局变量可能是一种不好的风格。请注意,导出的符号将与所有其他内核符号位于同一名称空间中。为了避免名称冲突,您应该为它们使用一些定义明确的前缀,通常是模块的名称和下划线。因此,如果您的模块之一名为
foo
并且您想要导出函数bar()
,则可以在foo
模块中使用如下代码:在另一个模块中,比如 buz,只需调用此函数:
注意,在内核模块中,您不能使用 libc(或其他库)功能以及许多常见的功能,例如内存管理、文件 I /O、网络等等,可能非常复杂。另请注意,内核模块调试不是一项简单的任务,许多错误将导致内核恐慌,而不是无害的分段错误。
因此,在将某些工作库移至内核空间之前请三思。也许最好将您的库分解为相同的“模块”,但将其(或其中的大部分)保留在用户空间中。
All kernel modules run in the same address space. To call one module from another, you need to export some symbols: functions or global variables. Though probably the use of global variables in this case is a bad style. Note that your exported symbols will be in the same name space as all other kernel symbols. To avoid name conflicts you should use some well-defined prefix for them, usually the name of the module and an underscore. So if one of your modules is called
foo
and you want to export functionbar()
, you could use code like this infoo
module:In the other module, say buz, just call this function:
Be noted, that in the kernel module you can't use libc (or other libraries) features and many usual things like memory management, file I/O, networking and so on, could be really complicated. Also note that kernel module debugging is not a trivial task and many errors will cause kernel panic instead of harmless Segmentation Fault.
So think thrice before moving some working library to the kernel space. Possibly it might be better to break your library into the same "modules" but keep it (or most part of it) in userspace.