0%

Linux基础复学(2)- 内核模块基础

前言

复习一下内核模块的几个基础部分内容。

内核模块

初始化和退出函数

分别使用module_init和module_exit设置模块的初始化和退出函数。

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
// mytest.c
#include <linux/init.h>
#include <linux/module.h>

static int __init my_init(void)
{
return 0;
}


static void __exit my_exit(void)
{
return 0;
}


module_init(my_init);
module_exit(my_exit);

/*模块信息声明*/

MODULE_LICENSE("GPL");
MODULE_AUTHOR("TEST");
MODULE_DESCRIPTINO("My test module");
MODULE_ALIAS("mytest");

Makefile 编写

模块都有对应的Makefile来编译。

1
2
3
4
5
6
7
8
9
10
11
KERNEL_DIR := /lib/modules/'uname -r'/build

mytest-objs := mytest.o
obj-m := mytest.o

all:
$(MAKE) -C $(KERNEL_DIR) M=$(PWD) modules;

clean:
$(MAKE) -C $(KERNEL_DIR) SUBDIRS=$(PWD) clean;
rm -f *k.o

模块参数

可以给模块传递参数,参数类型可以是byte, short, ushort, int, uint, long, ulong, char 和bool类型。

参数可能会在/sys/module/mytest/xxx,通过参数定义的perm可以控制该sys文件的访问权限,一般使用8进制定义,如S_IRUGO(0444),如果有写权限,那么root用户可以改写sys内容控制参数对应的全局变量。

1
2
3
4
static int debug=1;
module_param(debug, int, 0644);
MODULE_PARAM_DESC(debug, "enable debug feature.");

符号

不同的模块如果有依赖, 被依赖的模块可以导出API接口。

1
2
// 一般使用 EXPORT_SYMBOL_GPL(api_function)

内核导出的符号可以在/proc/kallsyms 中查看。

模块加载和卸载

使用inmod Module.ko 加载模块,会调用模块初始化函数, 如果返回为0则加载成功,否则加载失败。通过lsmod 可以查看所有加载的模块。

使用rmmod Module卸载模块,会调用模块退出函数。


行动,才不会被动!

欢迎关注个人公众号 微信 -> 搜索 -> fishmwei,沟通交流。

欢迎关注

博客地址: https://fishmwei.github.io

掘金主页: https://juejin.cn/user/2084329776486919