将设备驱动程序实现为一组内核模块

时间:2012-01-13 22:09:23

标签: linux architecture kernel kernel-module

我有一个用户空间库,用于通过串口与设备通信。该库相当复杂,执行许多任务,包括将标题放入有效载荷,分片消息,发送消息,处理响应,初始化设备等......

我想把这个库移到内核空间,我正在考虑将库拆分成几个定义良好的内核模块,以便

  • 我可以在未来打开门以换出图层(例如,用SPI图层换出USART图层)。
  • 开发会更容易。如果它被分割,我可以逐个将库迁移到内核空间。

以前有没有人做过这样的事情?在内核模块之间进行通信的最佳方式(在效率方面)是什么?我应该避免任何陷阱吗?

最后,有没有很好的驱动程序示例作为一组内核模块实现?

2 个答案:

答案 0 :(得分:0)

不确定这是否有帮助,但ALSA由每个不同声音芯片的许多不同模块组成,以及其他几个常见的模块:

$ lsmod | grep snd
snd_hrtimer            12744  1 
snd_hda_codec_realtek   330769  1 
snd_hda_intel          33390  2 
snd_usb_audio         118064  0 
snd_hda_codec         104802  2 snd_hda_codec_realtek,snd_hda_intel
snd_pcm                96714  3 snd_hda_intel,snd_usb_audio,snd_hda_codec
snd_hwdep              13668  2 snd_usb_audio,snd_hda_codec
snd_usbmidi_lib        25371  1 snd_usb_audio
snd_seq_midi           13324  0 
snd_rawmidi            30547  2 snd_usbmidi_lib,snd_seq_midi
snd_seq_midi_event     14899  1 snd_seq_midi
snd_seq                61896  3 snd_seq_midi,snd_seq_midi_event
snd_timer              29991  3 snd_hrtimer,snd_pcm,snd_seq
snd_seq_device         14540  3 snd_seq_midi,snd_rawmidi,snd_seq
snd                    68266  16 snd_hda_codec_realtek,snd_hda_intel,snd_usb_audio,snd_hda_codec,snd_pcm,snd_hwdep,snd_usbmidi_lib,snd_rawmidi,snd_seq,snd_timer,snd_seq_device
soundcore              12680  1 snd
snd_page_alloc         18529  2 snd_hda_intel,snd_pcm

重建依赖图是留给读者的练习。

答案 1 :(得分:0)

所有内核模块都在相同的地址空间中运行。要从另一个模块调用一个模块,您需要导出一些符号:函数或全局变量。虽然在这种情况下使用全局变量可能是一种糟糕的风格。请注意,导出的符号将与所有其他内核符号位于同一名称空间中。为避免名称冲突,您应该为它们使用一些明确定义的前缀,通常是模块的名称和下划线。因此,如果您的某个模块被调用foo并且您想导出函数bar(),则可以在foo模块中使用这样的代码:

void foo_bar(const char *prm) {
  printk (KERN_INFO "foo_bar(%s) was called\n", prm);
}
EXPORT_SYMBOL(foo_bar);

在另一个模块中,比如buz,只需调用此函数:

foo_bar("qux");

注意,在内核模块中你不能使用libc(或其他库)功能和许多常见的东西,如内存管理,文件I / O,网络等,可能是真的很复杂。另请注意,内核模块调试不是一项简单的任务,许多错误都会导致内核崩溃,而不是无害的分段错误。

因此在将一些工作库移动到内核空间之前要考虑三次。可能最好将您的库拆分为相同的“模块”,但将其(或大部分)保留在用户空间中。