如何通过一个简单的示例编写自己的 Linux 内核模块

举报
Tiamo_T 发表于 2022/08/08 10:43:05 2022/08/08
【摘要】 什么是内核模块? 内核模块是一段代码,可以根据需要从内核加载和卸载。

什么是内核模块?

内核模块是一段代码,可以根据需要从内核加载和卸载。

内核模块提供了一种简单的方法来扩展基本内核的功能,而无需再次重建或重新编译内核。大多数驱动程序都是作为 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 内核模块的基础知识。

【版权声明】本文为华为云社区用户原创内容,转载时必须标注文章的来源(华为云社区)、文章链接、文章作者等基本信息, 否则作者和本社区有权追究责任。如果您发现本社区中有涉嫌抄袭的内容,欢迎发送邮件进行举报,并提供相关证据,一经查实,本社区将立刻删除涉嫌侵权内容,举报邮箱: cloudbbs@huaweicloud.com
  • 点赞
  • 收藏
  • 关注作者

评论(0

0/1000
抱歉,系统识别当前为高风险访问,暂不支持该操作

全部回复

上滑加载中

设置昵称

在此一键设置昵称,即可参与社区互动!

*长度不超过10个汉字或20个英文字符,设置后3个月内不可修改。

*长度不超过10个汉字或20个英文字符,设置后3个月内不可修改。