Red Hat Training

A Red Hat training course is available for RHEL 8

2.12. 编译自定义的内核模块

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

先决条件

  • 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"); }

    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/4.18.0-305.el8.x86_64'
      CC [M]  /root/testmodule/test.o
      Building modules, stage 2.
      MODPOST 1 modules
    WARNING: modpost: missing MODULE_LICENSE() in /root/testmodule/test.o
    see include/linux/module.h for more information
      CC      /root/testmodule/test.mod.o
      LD [M]  /root/testmodule/test.ko
    make: Leaving directory '/usr/src/kernels/4.18.0-305.el8.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/4.18.0-305.el8.x86_64/test.ko
  5. 验证内核模块是否成功载入:

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

    # dmesg
    [74422.545004] Hello World
                    This is a test

其它资源