编写一个 Linux 内核模块
作者:解琛
时间:2020 年 8 月 16 日
一、实验环境
jerome@jerome:~$ uname -a
Linux jerome 5.4.0-42-generic #46~18.04.1-Ubuntu SMP Fri Jul 10 07:21:24 UTC 2020 x86_64 x86_64 x86_64 GNU/Linux
jerome@jerome:~$ lsb_release -a
No LSB modules are available.
Distributor ID: Ubuntu
Description: Ubuntu 18.04.4 LTS
Release: 18.04
Codename: bionic
二、Linux 内核模块相关命令
命令 | 作用 |
---|---|
lsmod | 用于显示所有已载入系统的内核模块。 |
insmod | 用于加载内核模块,通常可载入的模块一般是设备驱动程序 |
rmmod | 用于卸载不需要的模块。 |
modinfo | 用于显示内核模块的相关信息。 |
depmod | 用于分析检测内核模块之间的依赖关系。 |
modprobe | 同样用于加载内核模块,与insmod不同,modprobe会根据depmod产生的依赖关系,加载依赖的的其他模块。 |
三、程序架构
内核模块程序的基本结构包括了以下几个部分:
- 头文件;
- 内核模块加载/卸载函数;
- 内核模块的参数;
- 内核模块导出符号;
- 内核模块的许可证;
- 内核模块的其他信息,如作者,模块的描述信息,模块的别名等;
四、编写一个内核模块
4.1 头文件
#include <linux/init.h>
#include <linux/module.h>
4.1.1 init.h
位于 lib/modules/5.4.0-42-generic/build/include/linux/init.h。
/* These are for everybody (although not all archs will actually
discard it in modules) */
#define __init __section(.init.text) __cold notrace
#define __initdata __section(.init.data)
#define __initconst __constsection(.init.rodata)
#define __exitdata __section(.exit.data)
#define __exit_call __used __section(.exitcall.exit)
/**
* module_init() - driver initialization entry point
* @x: function to be run at kernel boot time or module insertion
*
* module_init() will either be called during do_initcalls() (if
* builtin) or at module insertion time (if a module).
* There can only
* be one per module.
*/
#define module_init(x) __initcall(x);
/**
* module_exit() - driver exit entry point
* @x: function to be run when driver is removed
*
* module_exit() will wrap the driver clean-up code
* with cleanup_module() when used with rmmod when
* the driver is a module.
* the driver is statically
* compiled into the kernel, module_exit() has no effect.
* There can only be one per module.
*/
#define module_exit(x) __exitcall(x);
init.h 头文件主要包含了内核模块的加载、卸载函数的声明,还有一些宏定义,因此,只要涉及内核模块的编程,就需要加上该头文件。
4.1.2 module.h
位于 lib/modules/5.4.0-42-generic/build/include/linux/module.h。
/* Generic info of form tag = "info" */
#define MODULE_INFO(tag, info) __MODULE_INFO(