人生难得几回搏,此时不搏待何时。这篇文章主要讲述内核模块实验奔跑吧Linux内核相关的知识,希望能为你提供帮助。
文章目录
- ??Debug??
- ??可复用Makefile??
- ??模块代码??
- ??Makefile??
- ??执行??
- ??验证??
- ??加载模块??
- ??验证模块是否加载成功 —— lsmod??
- ??验证模块是否加载成功 —— /sys/modules/*??
- ??卸载模块??
- ??给模块传递参数??
- ??符号共享??
- ??其他类型的符号??
- ??链接其它本地文件??
- ??查看系统文件内容??
Debug 可复用Makefile如果你想这么写Makefile,可能不太起作用,虽然好像能够具备良好的易用性。建议还是针对性地将文件名显示地写出来,就像下面这样,只需要改注释的那两行即可。(目前没有解决这个问题)
# Makefile to make module
BASEINCLUDE ?= /lib/modules/`uname -r`/build
# MODULE_NAME-objs := TARGET_FILE.o (TARGET_FILE.c)
parm_module-objs := module_parm.o
# obj-m := MODULE_NAME.o
obj-m := parm_module.o # module.o
all:
$(MAKE) -C $(BASEINCLUDE) M=`pwd` modules
clean:
$(MAKE) -C $(BASEINCLUDE) M=`pwd` clean
rm -f *.ko
模块代码
// my_test.c
#include < linux/init.h> // 包含了module_init()、module_exit()函数申明
#include < linux/module.h> // MODULE_xxx
// 模块入口,内核在初始化各个模块时有优先级顺序,内核把所有模块的初始化函数都存放在一个特别的段中来管理
static int __init my_test_init(void)
printk("my first kernel module init.\\n");
return 0;
// 模块退出函数
static void __exit my_test_exit(void)
printk("goodbye.\\n");
module_init(my_test_init);
module_exit(my_test_exit);
MODULE_LICENSE("GPL");
MODULE_AUTHOR("Jia ming");
MODULE_DESCRIPTION("my test kernel module.");
MODULE_ALIAS("mytest"); // 为用户空间提供合适的别名
Makefile
BASEINCLUDE ?= /lib/modules/`uname -r`/build # 模块安装路径
mytest-objs := my_test.o # 目标文件
obj-m := mytest.o # 定义模块名
all:
$(MAKE) -C $(BASEINCLUDE) M=$(PWD) modules;
clean:
$(MAKE) -C $(BASEINCLUDE) M=$(PWD) clean;
rm -f *.ko;
执行
jiaming@ubuntu:~/Documents/CProject$ tree .
.
├── Makefile
└── my_test.c
0 directories, 2 files
jiaming@ubuntu:~/Documents/CProject$ make
make -C /lib/modules/`uname -r`/build M=/home/jiaming/Documents/CProject modules;
make[1]: Entering directory /usr/src/linux-headers-5.10.0-1044-oem
CC [M]/home/jiaming/Documents/CProject/my_test.o
LD [M]/home/jiaming/Documents/CProject/mytest.o
MODPOST /home/jiaming/Documents/CProject/Module.symvers
CC [M]/home/jiaming/Documents/CProject/mytest.mod.o
LD [M]/home/jiaming/Documents/CProject/mytest.ko
make[1]: Leaving directory /usr/src/linux-headers-5.10.0-1044-oem
jiaming@ubuntu:~/Documents/CProject$ tree . # 编译完成后会生成 mytest.ko 文件
.
├── Makefile
├── modules.order
├── Module.symvers
├── my_test.c
├── mytest.ko
├── mytest.mod
├── mytest.mod.c
├── mytest.mod.o
├── my_test.o
└── mytest.o
0 directories, 10 files
验证
jiaming@ubuntu:~/Documents/CProject$ file mytest.ko # x86_64 ELF 文件
mytest.ko: ELF 64-bit LSB relocatable, x86-64, version 1 (SYSV), BuildID[sha1]=80fe0e29ec10947eedd66ab3b21be2ab33f3b533, not stripped
jiaming@ubuntu:~/Documents/CProject$ modinfo mytest.ko
filename:/home/jiaming/Documents/CProject/mytest.ko
alias:mytest
description:my test kernel module.
author:Jia ming
license:GPL
srcversion:B30B37B2BFE0784D8BC61C4
depends:
retpoline:Y
name:mytest
vermagic:5.10.0-1044-oem SMP mod_unload modversions
加载模块?
?sudo insmod mytest.ko?
??
?dmesg?
?? 查看 ??printk?
? 输出内容。...
[182158.234851] [drm] ib test on ring 2 succeeded in 0 usecs
[182158.234864] [drm] ib test on ring 3 succeeded in 0 usecs
[182158.234880] [drm] ib test on ring 4 succeeded in 0 usecs
[184937.411931] my first kernel module init.
验证模块是否加载成功 —— lsmod
jiaming@ubuntu:~/Documents/CProject$ lsmod
ModuleSizeUsed by
mytest163840
ccm204809
hid_generic163840
...
验证模块是否加载成功 —— /sys/modules/*加载完模块后,系统会在该目录下新建一个目录。
jiaming@ubuntu:/sys/module$ ll | grep mytest
drwxr-xr-x5 root root 0 Aug 31 11:09 mytest/
卸载模块
sudo rmmod mytest
- ?
?dmesg?
? 命令查看:
...
[185276.971010] goodbye.
- ?
?lsmod?
? 中没有 mytest 模块。 - ?
?/sys/modules?
? 中没有 mytest 目录。
#include < linux/init.h> // 包含了module_init()、module_exit()函数申明
#include < linux/module.h> // MODULE_xxx
static int debug = 1;
module_param(debug, int, 0644);
MODULE_PARM_DESC(debug, "enable debugging information");
#define dprintk(args...) \\
if(debug) \\
printk(KERN_DEBUG args); \\
static int mytest = 100;
module_param(mytest, int, 0644);
MODULE_PARM_DESC(mytest, "test for module parameter");
// 模块入口,内核在初始化各个模块时有优先级顺序,内核把所有模块的初始化函数都存放在一个特别的段中来管理
static int __init my_test_init(void)
dprintk("my first kernel module init.\\n");
dprintk("module parameter=%d\\n", mytest);
return 0;
// 模块退出函数
static void __exit my_test_exit(void)
printk("goodbye.\\n");
module_init(my_test_init);
module_exit(my_test_exit);
MODULE_LICENSE("GPL");
MODULE_AUTHOR("Jia ming");
MODULE_DESCRIPTION("my test kernel module.");
MODULE_ALIAS("mytest");
传入参数
??
?sudo insmod mytest.ko mytest=200?
?查看结果
??
?dmesg?
? 查看...
[185891.125462] my first kernel module init.
[185891.125473] module parameter=200
符号共享模块之间相互调用。
EXPORT_SYMBOL() # 把函数或符号对全部内核代码公开,将函数以符号的方式导出给内核中的其它模块使用
EXPORT_SYMBOL_GPL() # 只能包含 GPL 许可的模块,MODULE_LICENSE("GPL")
导出的内核符号表可以通过 ?
?/proc/kallsyms?
? 查看...
0000000000000000 t cleanup_module [video]
0000000000000000 T acpi_video_get_edid[video]
0000000000000000 T acpi_video_unregister[video]
0000000000000000 T acpi_video_get_backlight_type[video]
0000000000000000 T acpi_video_set_dmi_backlight_type[video]
0000000000000000 t acpi_video_detect_exit [video]
0000000000000000 T acpi_video_register[video]
0000000000000000 t bpf_prog_6deef7357e7b4530[bpf]
0000000000000000 t bpf_prog_6deef7357e7b4530[bpf]
...
【内核模块实验奔跑吧Linux内核】?
?符号在内核地址空间中的地址;符号属性;符号的字符串;哪些内核模块在使用这些符号?
?module1_file.c
#include < linux/init.h> // 包含了module_init()、module_exit()函数申明
#include < linux/module.h> // MODULE_xxx
static int debug = 1;
module_param(debug, int, 0644);
MODULE_PARM_DESC(debug, "enable debugging information");
#define dprintk(args...) \\
if(debug) \\
printk(KERN_DEBUG args); \\
static int mytest = 100;
module_param(mytest, int, 0644);
MODULE_PARM_DESC(mytest, "test for module parameter");
// 模块入口,内核在初始化各个模块时有优先级顺序,内核把所有模块的初始化函数都存放在一个特别的段中来管理
static int __init my_test_init(void)
dprintk("my first kernel module init.\\n");
dprintk("module parameter=%d\\n", mytest);
return 0;
// 模块退出函数
static void __exit my_test_exit(void)
printk("goodbye.\\n");
static int getvalue(void)
return mytest;
EXPORT_SYMBOL(getvalue);
module_init(my_test_init);
module_exit(my_test_exit);
MODULE_LICENSE("GPL");
MODULE_AUTHOR("Jiaming");
MODULE_DESCRIPTION("my test kernel module.");
MODULE_ALIAS("module1");
Makefile
# Makefile to make module
BASEINCLUDE ?= /lib/modules/`uname -r`/build
# MODULE_NAME-objs := TARGET_FILE.o (TARGET_FILE.c)
module1-objs := module1_file.o
# obj-m := MODULE_NAME.o
obj-m := module1.o
all:
$(MAKE) -C $(BASEINCLUDE) M=`pwd` modules
clean:
$(MAKE) -C $(BASEINCLUDE) M=`pwd` clean
rm -f *.ko
module2_file.c
#include < linux/init.h> // 包含了module_init()、module_exit()函数申明
#include < linux/module.h> // MODULE_xxx
extern int getvalue(void);
static int debug = 1;
module_param(debug, int, 0644);
MODULE_PARM_DESC(debug, "enable debugging information");
#define dprintk(args...) \\
if(debug) \\
printk(KERN_DEBUG args); \\
// static int mytest = 100;
// module_param(mytest, int, 0644);
// MODULE_PARM_DESC(mytest, "test for module parameter");
// 模块入口,内核在初始化各个模块时有优先级顺序,内核把所有模块的初始化函数都存放在一个特别的段中来管理
static int __init my_test_init(void)
dprintk("my second kernel module init.\\n");
static int mytest;
mytest = getvalue();
dprintk("module parameter=%d\\n", mytest);
return 0;
// 模块退出函数
static void __exit my_test_exit(void)
printk("goodbye.\\n");
module_init(my_test_init);
module_exit(my_test_e
推荐阅读
- CommandLinux 绑定 CPU 核 以及 htop 命令
- Java流处理之转换编码的转换流
- 别再说你不知道分布式事务了
- Java6对synchronized的优化-锁升级过程详细过程
- 引导启动程序
- #云原生征文#深入了解k8s的Deployment
- 《Linux内核实时性以及网络实时性的研究》
- Linux 0.11Makefile
- 文件系统实验奔跑吧Linux内核