加载和卸载内核模块
Linux内核模块可以根据需要加载到内核或从内核中卸载。这可以在不重新编译内核或重启系统的情况下完成,并且可以增强系统的功能。
如果没有内核模块,操作系统将不得不把所有预期的功能都包含在基本内核中。这会导致内存浪费,因为大多数这些系统不会经常使用。此外,用户每次需要新功能时都需要重新构建和重启基本内核。
内核模块具有.ko扩展名,它们通常位于标准Linux系统中的/lib/modules//kernel/目录中。
Linux内核模块中的主要模块包括:文件系统驱动程序、设备驱动程序和系统调用。
要将模块插入内核,请使用insmod命令。该命令的语法如下:
insmod <module_name>.ko
要从内核中删除模块,请使用rmmod命令。正在被程序使用的模块无法删除。rmmod命令的语法如下:
rmmod <module_name>.ko
可以使用lsmod命令查看新创建的模块。此命令显示当前加载到系统中的可加载内核模块,如下所示:
创建和加载内核模块
创建内核模块的步骤如下:
让我们首先编写一个**example.c**程序:
首先,添加头文件:
#include <linux/kernel.h> #include <linux/init.h> #include <linux/module.h>
接下来,添加模块的描述和作者详细信息。不要忘记添加许可证:
MODULE_DESCRIPTION("Kernel module 1"); MODULE_AUTHOR("Harry"); MODULE_LICENSE("GPL");
现在让我们看看如何创建一个内核模块:
#include <linux/kernel.h> #include <linux/init.h> #include <linux/module.h> MODULE_DESCRIPTION("Kernel module 1 "); MODULE_AUTHOR("Harry"); MODULE_LICENSE("GPL"); static int example_init(void) { pr_debug("Welcome! Good to have you here!
"); return 0; } static void example_exit(void) { pr_debug("Goodbye!
"); } module_init(example_init); module_exit(example_exit);
上述程序中生成的日志信息不会显示在控制台中,而是保存在专门预留的内存区域中。日志守护程序 (syslog) 可以从该内存区域中恢复这些信息。
现在让我们看看如何编译我们的内核模块:
标准编译方法是kbuild。它使用两个文件:Makefile和Kbuild文件进行编译过程。Kbuild是Linux内核构建系统。
对于Makefile:
KDIR = home/dept/so2/linux kbuild: make -C $(KDIR) M=`pwd` clean: make -C $(KDIR) M=`pwd` clean
如上例所示,在Makefile文件中调用make会导致在内核源代码目录(即home/employee/so2/linux)中调用make,并引用当前目录(即M = `pwd`)。这个过程最终会导致读取当前目录中的Kbuild文件,并按照该文件中指示的指令编译模块。
现在编译模块:
EXTRA_CFLAGS = -Wall -g obj-m = example.o
插入模块:
insmod example.ko
现在,可以使用lsmod命令查看新创建的模块。lsmod命令显示当前加载的可加载内核模块。
$lsmod demo glue_helper ssdhci_acpi sdhci_cpi ahci
可以使用dmesg命令查看上述输出。此命令用于写入Linux中的内核消息。
$dmesg | tail -2 Welcome! Good to have you here! Goodbye!
构建模块后,将创建以下文件:
- example.o - 这是链接前的模块目标文件
- example.mod.c - 此文件包含模块信息
- example.mod.o - 这是编译和链接example.mod.c后创建的文件
- modules.order - 这指定了两个或三个模块的链接顺序
- modules.symvers - 如果存在任何符号版本,则指定这些符号版本。
- example.ko - 这是链接example.o和example.mod.o后创建的模块内核目标文件
现在让我们回顾一下上面我们看到的内容。
加载内核模块
要加载内核模块,可以使用insmod命令:
$insmod example.ko
现在,让我们显示模块的内容:
dmesg命令用于显示内核消息。
# dmesg | tail -2 Welcome! Good to have you here! Goodbye!