可以通过输入命令列出当前加载的所有内核模块,此命令将在三列中列出当前的内核模块:名称、大小和使用模块的位置。

  1. [root@ip-172-16-1-245 ~]# lsmod
  2. Module Size Used by
  3. intel_rapl_msr 16384 0
  4. intel_rapl_common 24576 1 intel_rapl_msr
  5. isst_if_common 16384 0
  6. nfit 65536 0
  7. libnvdimm 192512 1 nfit
  8. ppdev 20480 0
  9. rapl 20480 0
  10. pcspkr 16384 0
  11. parport_pc 32768 0
  12. parport 57344 2 parport_pc,ppdev
  13. i2c_piix4 24576 0
  14. ip_tables 28672 0
  15. xfs 1515520 1
  16. libcrc32c 16384 1 xfs
  17. crct10dif_pclmul 16384 1
  18. crc32_pclmul 16384 0
  19. crc32c_intel 24576 1
  20. nvme 45056 1
  21. ghash_clmulni_intel 16384 0
  22. nvme_core 110592 3 nvme
  23. ena 114688 0
  24. serio_raw 16384 0
  25. t10_pi 16384 1 nvme_core
  26. dm_mirror 28672 0
  27. dm_region_hash 20480 1 dm_mirror
  28. dm_log 20480 2 dm_region_hash,dm_mirror
  29. dm_mod 151552 2 dm_log,dm_mirror


编写内核模块

要编写内核模块,需要有内核源码,内核源码是放到/usr/src/kernels/下面的。我们需要装一个包:

yum install kernel-devel
sudo yum group install "Development Tools"  # 开发者套件

装完这个包以后,就能到对应目录下看到内核源码了。

下面的程序编写了一个非常基本的内核模块,它在内核模块加载和卸载时打印适当的消息。

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

Makefile

obj-m := test.o

编译模块

make -C /lib/modules/$(uname -r)/build M=/root/testmodule modules

运行成功后会生成很多文件,其中包括simple.ko 这个就是我们编译出来的内核模块

加载模块

运行时加载内核模块

[root@ip-172-16-1-245 ch2]# insmod simple.ko 
[root@ip-172-16-1-245 ch2]# lsmod  | grep simple
simple                 16384  0
[root@ip-172-16-1-245 ch2]# rmmod simple.ko # 移除模块

The insmod program inserts a single module into the kernel. This process requires you to have already loaded any modules on which the module you’re loading relies. The modprobe program, by contrast, automatically loads any depended-on modules and so is generally the preferred way to do the job.

加载完模块以后可以查看dmesg 日志

[94475.463304] Hello World
                This is a test

另一种复制文件的方式加载

Optional: check the contents of the /root/testmodule/ directory:

ls -l /root/testmodule/
total 452
-rw-r—r--. 1 root root     16 Jul 12 10:16 Makefile
-rw-r—r--. 1 root root     32 Jul 12 10:16 modules.order
-rw-r—r--. 1 root root      0 Jul 12 10:16 Module.symvers
-rw-r—r--. 1 root root    197 Jul 12 10:15 test.c
-rw-r—r--. 1 root root 219736 Jul 12 10:16 test.ko
-rw-r—r--. 1 root root    826 Jul 12 10:16 test.mod.c
-rw-r—r--. 1 root root 113760 Jul 12 10:16 test.mod.o
-rw-r—r--. 1 root root 107424 Jul 12 10:16 test.o
Copy the kernel module to the /lib/modules/$(uname -r)/ directory:

# cp /root/testmodule/test.ko /lib/modules/$(uname -r)/
Update the modular dependency list:

# depmod -a
Load the kernel module:

# modprobe -v test
insmod /lib/modules/4.18.0-305.el8.x86_64/test.ko
Verify that the kernel module was successfully loaded:

# lsmod | grep test
test                   16384  0
Read the latest messages from the kernel ring buffer:

# dmesg
…
[74422.545004] Hello World
                This is a test

# modprobe -r test 移除模块

系统启动时加载内核模块

Select a kernel module you want to load during the boot process.

The modules are located in the /lib/modules/$(uname -r)/kernel/<SUBSYSTEM>/ directory.

Create a configuration file for the module:

# echo <MODULE_NAME> > /etc/modules-load.d/<MODULE_NAME>.conf
NOTE
When entering the name of a kernel module, do not append the .ko.xz extension to the end of the name. Kernel module names do not have extensions; their corresponding files do.

Optionally, after reboot, verify the relevant module was loaded:

$ lsmod | grep <MODULE_NAME>
The example command above should succeed and display the relevant kernel module.

内核模块依赖

依赖关系文件
/lib/modules/4.18.0-305.12.1.el8_4.x86_64/modules.dep
管理依赖关系命令
depmod -a