如何通过一个简单的示例编写自己的 Linux 内核模块
什么是内核模块?
内核模块是一段代码,可以根据需要从内核加载和卸载。
内核模块提供了一种简单的方法来扩展基本内核的功能,而无需再次重建或重新编译内核。大多数驱动程序都是作为 Linux 内核模块实现的。当不需要这些驱动程序时,我们可以只卸载特定的驱动程序,这将减小内核映像的大小。
内核模块将具有 .ko 扩展名。在普通的 linux 系统上,内核模块将驻留在 /lib/modules/<kernel_version>/kernel/ 目录中。
前面我们讨论了如何从源代码编译内核。
本教程解释了如何使用一个简单的 Hello World 示例编写内核模块。
I. 操作内核模块的实用程序
1. lsmod - 列出已经加载的模块
lsmod 命令将列出已加载到内核中的模块,如下所示。
# lsmod
Module Size Used by
ppp_deflate 12806 0
zlib_deflate 26445 1 ppp_deflate
bsd_comp 12785 0
..
2. insmod – 将模块插入内核
insmod 命令将在内核中插入一个新模块,如下所示。
# insmod /lib/modules/3.5.0-19-generic/kernel/fs/squashfs/squashfs.ko
# lsmod | grep "squash"
squashfs 35834 0
3. modinfo - 显示模块信息
modinfo 命令将显示有关内核模块的信息,如下所示。
# modinfo /lib/modules/3.5.0-19-generic/kernel/fs/squashfs/squashfs.ko
filename: /lib/modules/3.5.0-19-generic/kernel/fs/squashfs/squashfs.ko
license: GPL
author: Phillip Lougher
description: squashfs 4.0, a compressed read-only filesystem
srcversion: 89B46A0667BD5F2494C4C72
depends:
intree: Y
vermagic: 3.5.0-19-generic SMP mod_unload modversions 686
4. rmmod - 从内核中删除模块
rmmod 命令将从内核中删除一个模块。您不能删除已被任何程序使用的模块。
# rmmod squashfs.ko
5. modprobe - 从内核中添加或删除模块
modprobe 是一个智能命令,它将根据模块之间的依赖关系加载/卸载模块。
二、编写一个简单的 Hello World 内核模块
1.安装linux头文件
您需要先安装 linux-headers-..,如下所示。根据您的发行版,使用 apt-get 或 yum。
# apt-get install build-essential linux-headers-$(uname -r)
2.Hello World模块源码
接下来,用 C 编程语言创建以下 hello.c 模块。
#include <linux/module.h> // included for all kernel modules
#include <linux/kernel.h> // included for KERN_INFO
#include <linux/init.h> // included for __init and __exit macros
MODULE_LICENSE("GPL");
MODULE_AUTHOR("Lakshmanan");
MODULE_DESCRIPTION("A Simple Hello World module");
static int __init hello_init(void)
{
printk(KERN_INFO "Hello world!\n");
return 0; // Non-zero return means that the module couldn't be loaded.
}
static void __exit hello_cleanup(void)
{
printk(KERN_INFO "Cleaning up module.\n");
}
module_init(hello_init);
module_exit(hello_cleanup);
警告:所有内核模块都将在内核空间上运行,这是一种高特权模式。所以要小心你在内核模块中写的东西。
3. 创建 Makefile 编译内核模块
以下 makefile 可用于编译上述基本的 hello world 内核模块。
obj-m += hello.o
all:
make -C /lib/modules/$(shell uname -r)/build M=$(PWD) modules
clean:
make -C /lib/modules/$(shell uname -r)/build M=$(PWD) clean
使用make 命令编译 hello world 内核模块,如下所示。
# make
make -C /lib/modules/3.5.0-19-generic/build M=/home/lakshmanan/a modules
make[1]: Entering directory `/usr/src/linux-headers-3.5.0-19-generic'
CC [M] /home/lakshmanan/a/hello.o
Building modules, stage 2.
MODPOST 1 modules
CC /home/lakshmanan/a/hello.mod.o
LD [M] /home/lakshmanan/a/hello.ko
make[1]: Leaving directory `/usr/src/linux-headers-3.5.0-19-generic'
以上将创建 hello.ko 文件,这是我们的示例内核模块。
4. 插入或移除示例内核模块
现在我们有了 hello.ko 文件,我们可以使用 insmod 命令将此模块插入内核,如下所示。
# insmod hello.ko
# dmesg | tail -1
[ 8394.731865] Hello world!
# rmmod hello.ko
# dmesg | tail -1
[ 8707.989819] Cleaning up module.
当一个模块插入内核时,会调用module_init宏,它会调用函数hello_init。同样,当使用 rmmod 删除模块时,将调用 module_exit 宏,该宏将调用 hello_exit。使用 dmesg 命令,我们可以看到示例内核模块的输出。
请注意 printk 是一个在内核中定义的函数,它的行为类似于 IO 库中的 printf。请记住,您不能使用内核模块中的任何库函数。
现在您已经学习了创建自己的 Linux 内核模块的基础知识。
- 点赞
- 收藏
- 关注作者
评论(0)