内核模块是代码组件,可以在需要时由内核加载和卸载。它们用于扩展内核的功能,而无需重新启动系统。内核模块的主要应用之一是编写设备驱动程序。在本文中,我将向您展示如何编写和编译一个简单的内核模块,它将警报写入内核日志。
我将再次编写我的代码st ubuntu运行4.10.0-28-generic的linux内核。建立内核开发环境方面有一些选择。最简单的方法是安装Linux的分发,并使用在其上编译的内核。或者,您可以访问像Kernel.org这样的网页以下载并构建最新的内核版本。
我将显示的示例是用C的写作。有两个主要组成部分我们需要编写我们的内核模块,模块的源代码以及Makefile来编译模块。当模块已加载并从内核中删除时,我们的模块的一般概念将是执行代码。添加模块时,我们将作为警报将“Hello World”打印到内核日志。当模块被删除时,我们将作为警报将“再见世界”打印到内核日志。
从代码的顶部开始,我们需要将Linux / init.h和linux / module.h导入我们的代码,为我们提供加载和删除内核模块所需的组件。 module_license线条不是特别重要的,它只是通知内核这个模块是开源的。初始设置后,我们定义了两个功能。 hello_init(void)函数是我们将调用的模块加载到内核时,hello_exit(void)函数是我们将在从内核中删除模块时调用的。要将这些功能链接到相应的事件,我们使用module_init和module_exit。函数module_init占用功能,并将其链接到模块加载事件。类似地,Module_exit函数占用函数并将其链接到模块删除事件。在这些事件中的任何一个上,执行链接函数。
函数的实际逻辑不是太复杂。 Function Printk是Print的特殊实现,它将提供的文本写入内核日志。 kern_alert定义了打印的文本的格式,这是一个警报级日志行。我们使用它,因为Printf功能在内核模式下不可用,因此使用Printk打印到日志是下一个最佳选择。
现在我们已经定义了实际模块的所有逻辑,我们可以创建makefile来编译它。
Makefile的一般思想是指向内核目录的构建过程。如果您尝试输入uname -R,则会看到该命令写入Linux内核版本。运行此Makefile时,它会产生启用此模块所需的正确文件。
现在我们有我们需要的文件,我们可以将它们加载到内核中。 要将模块加载到内核中,我们使用insmod命令。 要删除模块,我们使用rmmod命令。 请注意,要运行这些命令,您必须使用root帐户。 要查看此内核模块的结果,我们需要导航到内核日志并读取它。 在大多数Linux系统上,可以在/var/log/kern.log中找到。 在这里,您应该看到Hello World和Goodbye World消息。 这向我们展示了我们编写的模块已成功添加并从内核中删除!