3.11. 编译自定义内核模块

您可以根据硬件和软件级别的各种配置根据需要构建抽样内核模块。

先决条件

  • 已安装 kernel-develgccelfutils-libelf-devel 软件包。

    # dnf install kernel-devel-$(uname -r) gcc elfutils-libelf-devel
  • 有 root 权限。
  • 您创建了 /root/testmodule/ 目录,供您编译自定义内核模块。

步骤

  1. 创建包含以下内容的 /root/testmodule/test.c 文件:

    #include <linux/module.h>
    #include <linux/kernel.h>
    
    int init_module(void)
        { printk("Hello World\n This is a test\n"); return 0; }
    
    void cleanup_module(void)
        { printk("Good Bye World"); }
    
    MODULE_LICENSE("GPL");

    test.c 文件是一个源文件,它为内核模块提供主要功能。文件已创建在专用的 /root/testmodule/ 目录中,用于组织目的。在模块编译后,/root/testmodule/ 目录将包含多个文件。

    test.c 文件包括来自系统库:

    • 在示例代码中,printk() 函数需要 linux/kernel.h 头文件。
    • linux/module.h 文件包含函数声明和宏定义,可在使用 C 编程语言编写的多个源文件之间共享。
  2. 按照 init_module ()cleanup_module () 函数启动和结束内核日志记录函数 printk (),后者会打印文本。
  3. 使用以下内容创建 /root/testmodule/Makefile 文件。

    obj-m := test.o

    Makefile 包含编译器必须专门生成名为 test.o 的对象文件的指令。obj-m 指令指定生成的 test.ko 文件将作为可加载的内核模块进行编译。或者,obj-y 指令将指示构建 test.ko 作为内置内核模块。

  4. 编译内核模块。

    # make -C /lib/modules/$(uname -r)/build M=/root/testmodule modules
    make: Entering directory '/usr/src/kernels/5.14.0-70.17.1.el9_0.x86_64'
      CC [M]  /root/testmodule/test.o
      MODPOST /root/testmodule/Module.symvers
      CC [M]  /root/testmodule/test.mod.o
      LD [M]  /root/testmodule/test.ko
      BTF [M] /root/testmodule/test.ko
    Skipping BTF generation for /root/testmodule/test.ko due to unavailability of vmlinux
    make: Leaving directory '/usr/src/kernels/5.14.0-70.17.1.el9_0.x86_64'

    编译器将它们链接成最终内核模块(test.ko)之前,会为每个源文件(test.c)创建一个对象文件(test.c)来作为中间步骤。

    成功编译后,/root/testmodule/ 包含与编译的自定义内核模块相关的其他文件。已编译的模块本身由 test.ko 文件表示。

验证

  1. 可选:检查 /root/testmodule/ 目录的内容:

    # ls -l /root/testmodule/
    total 152
    -rw-r—​r--. 1 root root    16 Jul 26 08:19 Makefile
    -rw-r—​r--. 1 root root    25 Jul 26 08:20 modules.order
    -rw-r—​r--. 1 root root     0 Jul 26 08:20 Module.symvers
    -rw-r—​r--. 1 root root   224 Jul 26 08:18 test.c
    -rw-r—​r--. 1 root root 62176 Jul 26 08:20 test.ko
    -rw-r—​r--. 1 root root    25 Jul 26 08:20 test.mod
    -rw-r—​r--. 1 root root   849 Jul 26 08:20 test.mod.c
    -rw-r—​r--. 1 root root 50936 Jul 26 08:20 test.mod.o
    -rw-r—​r--. 1 root root 12912 Jul 26 08:20 test.o
  2. 将内核模块复制到 /lib/modules/$(uname -r)/ 目录中:

    # cp /root/testmodule/test.ko /lib/modules/$(uname -r)/
  3. 更新模块依赖项列表:

    # depmod -a
  4. 载入内核模块:

    # modprobe -v test
    insmod /lib/modules/5.14.0-1.el9.x86_64/test.ko
  5. 验证内核模块是否已成功载入:

    # lsmod | grep test
    test                   16384  0
  6. 从内核环缓冲中读取最新信息:

    # dmesg
    [74422.545004] Hello World
                    This is a test

其他资源