linux make modules 命令详解

发布时间 2023-10-20 17:45:04作者: imxiangzi

一、Linux 内核模块编译的本质
make modules 命令的执行路径只能是内核源码顶层目录,执行结果是:读取内核源码顶层目录中的 Makefile 文件,找到里面定义的 modules 目标。(更详细的内容不在此处分析)

我们可以建立一个文件夹存放模块源代码,写一个 Makefile,里面写 make modules 目标,但是要切换到 linux 源码目录中找顶层目录的 Makefile 来编译。

# hello 是模块名,也是对应的 c 文件名
obj-m += hello.o
# KDIR 内核源码路径,根据自己需要设置
# X86 源码路径统一是 /lib/modules/$(shell uname -r)/build
# 如果要编译 ARM 的模块,则修改成 ARM 的内核源码路径
KDIR := /home/backvm/work0/linux_ker/linux-3.5.2
all:
make -C $(KDIR) M=$(PWD) modules
@rm -f *.o *.mod.o *.mod.c *.symvers *.markers *.unsigned *.order *~
clean:
make -C $(KDIR) M=$(PWD) modules clean
rm -f *.o *.mod.o *.mod.c *.symvers *.markers *.unsigned *.order *~
1
2
3
4
5
6
7
8
9
10
11
12
分析:-C 选项的作用是指将当前工作目录转移到你所指定的位置。“M=”选项的作用是,当用户需要以某个内核源码为基础,编译一个外部模块的话,需要在make modules 命令中加入“M=dir”,程序会自动到你所指定的dir目录中查找模块源码,将其编译,生成KO文件。

二、示例演示
root@zzz:test# ll
总用量 16
drwxr-xr-x 2 root root 4096 5月 2 13:05 ./
drwxr-xr-x 6 root root 4096 5月 1 19:02 ../
-rw-r--r-- 1 root root 359 5月 1 19:16 hello.c
-rw-r--r-- 1 root root 548 5月 1 19:16 Makefile
root@zzz:test# cat Makefile
# hello 是模块名,也是对应的 c 文件名
obj-m += hello.o
# KDIR 内核源码路径,根据自己需要设置
# X86 源码路径统一是 /lib/modules/$(shell uname -r)/build
# 如果要编译 ARM 的模块,则修改成 ARM 的内核源码路径
KDIR := /home/backvm/work0/linux_ker/linux-3.5.2
all:
make -C $(KDIR) M=$(PWD) modules
@rm -f *.o *.mod.o *.mod.c *.symvers *.markers *.unsigned *.order *~
clean:
make -C $(KDIR) M=$(PWD) modules clean
rm -f *.o *.mod.o *.mod.c *.symvers *.markers *.unsigned *.order *~
root@zzz:test#
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
三、 linux 多模块编译
如何实现把模块中的一个函数导出给另外一个模块使用?

1) 多模块
EXPORT_SYMBOL(symbol);
1
这个宏是内核专门用来把一个模块的函数或变量导出,给其他模块使用。
源码示例:

calculate.c
--------
#include <linux/module.h>
#include <linux/init.h>

static int add_integer(int a,int b);
static int sub_integer(int a,int b);

EXPORT_SYMBOL(add_integer);
EXPORT_SYMBOL(sub_integer);

static int add_integer(int a,int b)
{
return a+b;
}
static int sub_integer(int a,int b)
{
return a-b;
}

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

static void __exit hello_exit(void)
{
}

module_init(hello_init);
module_exit(hello_exit);
MODULE_LICENSE("GPL");


hello.c
--------
#include <linux/module.h>
#include <linux/init.h>

extern int add_integer(int a,int b);
extern int sub_integer(int a,int b);

static int __init hello_init(void)
{
int res = add_integer(1,2);
printk("hello init: res = %d", res);
return 0;
}

static void __exit hello_exit(void)
{
int res = sub_integer(1,2);
printk("hello exit: res = %d", res);
}

module_init(hello_init);
module_exit(hello_exit);
MODULE_LICENSE("GPL");


Makefile
-------
# hello 是模块名,也是对应的 c 文件名
obj-m += hello.o calculate.o
# KDIR 内核源码路径,根据自己需要设置
# X86 源码路径统一是 /lib/modules/$(shell uname -r)/build
# 如果要编译 ARM 的模块,则修改成 ARM 的内核源码路径
KDIR := /home/backvm/work0/linux_ker/linux-3.5.2
all:
make -C $(KDIR) M=$(PWD) modules
@rm -f *.o *.mod.o *.mod.c *.symvers *.markers *.unsigned *.order *~
clean:
make -C $(KDIR) M=$(PWD) modules clean
rm -f *.o *.mod.o *.mod.c *.symvers *.markers *.unsigned *.order *~
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
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
root@backvm-virtual-machine:02_export# make
make -C /home/backvm/work0/linux_ker/linux-3.5.2 M=/home/backvm/work0/linux_ker/test/02_export modules
make[1]: Entering directory '/home/backvm/work0/linux_ker/linux-3.5.2'
CC [M] /home/backvm/work0/linux_ker/test/02_export/hello.o
CC [M] /home/backvm/work0/linux_ker/test/02_export/calculate.o
Building modules, stage 2.
MODPOST 2 modules
CC /home/backvm/work0/linux_ker/test/02_export/calculate.mod.o
LD [M] /home/backvm/work0/linux_ker/test/02_export/calculate.ko
CC /home/backvm/work0/linux_ker/test/02_export/hello.mod.o
LD [M] /home/backvm/work0/linux_ker/test/02_export/hello.ko
make[1]: Leaving directory '/home/backvm/work0/linux_ker/linux-3.5.2'
root@backvm-virtual-machine:02_export#
root@backvm-virtual-machine:02_export# modinfo hello.ko
filename: /home/backvm/work0/linux_ker/test/02_export/hello.ko
license: GPL
depends: calculate
vermagic: 3.5.2 mod_unload ARMv4 p2v8
root@backvm-virtual-machine:02_export# modinfo calculate.ko
filename: /home/backvm/work0/linux_ker/test/02_export/calculate.ko
license: GPL
depends:
vermagic: 3.5.2 mod_unload ARMv4 p2v8
root@backvm-virtual-machine:02_export#

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
2) 多文件单模块
多个 c 代码文件编译成一个 ko 文件。
注意:这些文件中只能有一个是以模块的形式编写,其他 c 文件都像普通 c语言文件一样。因为一个模块只能有一个加载函数和一个卸载函数。
Makefile 写法和单文件单模块有点不一样。


Makefile
-------
# hello 是模块名,也是对应的 c 文件名
obj-m += mulc.o # 最终模块名
mulc-objs = hello.o calculate.o # 源文件列表
# KDIR 内核源码路径,根据自己需要设置
# X86 源码路径统一是 /lib/modules/$(shell uname -r)/build
# 如果要编译 ARM 的模块,则修改成 ARM 的内核源码路径
KDIR := /home/backvm/work0/linux_ker/linux-3.5.2
all:
make -C $(KDIR) M=$(PWD) modules
@rm -f *.o *.mod.o *.mod.c *.symvers *.markers *.unsigned *.order *~
clean:
make -C $(KDIR) M=$(PWD) modules clean
rm -f *.o *.mod.o *.mod.c *.symvers *.markers *.unsigned *.order *~

 

calculate.c
--------
int add_integer(int a,int b)
{
return a+b;
}
int sub_integer(int a,int b)
{
return a-b;
}


hello.c
--------
#include <linux/module.h>
#include <linux/init.h>

extern int add_integer(int a,int b);
extern int sub_integer(int a,int b);

static int __init hello_init(void)
{
int res = add_integer(1,2);
printk("hello init: res = %d", res);
return 0;
}

static void __exit hello_exit(void)
{
int res = sub_integer(1,2);
printk("hello exit: res = %d", res);
}

module_init(hello_init);
module_exit(hello_exit);
MODULE_LICENSE("GPL");
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
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
root@backvm-virtual-machine:02_export_02# make
make -C /home/backvm/work0/linux_ker/linux-3.5.2 M=/home/backvm/work0/linux_ker/test/02_export_02 modules
make[1]: Entering directory '/home/backvm/work0/linux_ker/linux-3.5.2'
CC [M] /home/backvm/work0/linux_ker/test/02_export_02/hello.o
CC [M] /home/backvm/work0/linux_ker/test/02_export_02/calculate.o
LD [M] /home/backvm/work0/linux_ker/test/02_export_02/mulc.o
Building modules, stage 2.
MODPOST 1 modules
CC /home/backvm/work0/linux_ker/test/02_export_02/mulc.mod.o
LD [M] /home/backvm/work0/linux_ker/test/02_export_02/mulc.ko
make[1]: Leaving directory '/home/backvm/work0/linux_ker/linux-3.5.2'
root@backvm-virtual-machine:02_export_02# modinfo mulc.ko
filename: /home/backvm/work0/linux_ker/test/02_export_02/mulc.ko
license: GPL
depends:
vermagic: 3.5.2 mod_unload ARMv4 p2v8
root@backvm-virtual-machine:02_export_02#
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
四、编译所有 linux 文件
make -C $(MOD_SRC_DIR)/$(COMMON_DIR)/$${cpu}/ all

————————————————
版权声明:本文为CSDN博主「滨边美波她男友」的原创文章,遵循CC 4.0 BY-SA版权协议,转载请附上原文出处链接及本声明。
原文链接:https://blog.csdn.net/weixin_42109053/article/details/124526066