linux make modules 命令详解

文章详细介绍了Linux内核模块的编译过程,包括makemodules命令的执行原理、模块源代码组织、Makefile配置、不同架构的内核源码路径以及如何通过EXPORT_SYMBOL实现模块间函数导出。还展示了多文件编译成单模块的示例。
摘要由CSDN通过智能技术生成

原文链接:https://blog.csdn.net/weixin_42109053/article/details/124526066

一、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 ( K D I R ) M = (KDIR) M= (KDIR)M=(PWD) modules
@rm -f *.o *.mod.o *.mod.c *.symvers *.markers *.unsigned *.order *~
clean:
make -C ( K D I R ) M = (KDIR) M= (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 ( K D I R ) M = (KDIR) M= (KDIR)M=(PWD) modules
@rm -f *.o *.mod.o *.mod.c *.symvers *.markers *.unsigned *.order *~
clean:
make -C ( K D I R ) M = (KDIR) M= (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 ( K D I R ) M = (KDIR) M= (KDIR)M=(PWD) modules
@rm -f *.o *.mod.o *.mod.c *.symvers *.markers *.unsigned *.order *~
clean:
make -C ( K D I R ) M = (KDIR) M= (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 ( K D I R ) M = (KDIR) M= (KDIR)M=(PWD) modules
@rm -f *.o *.mod.o *.mod.c *.symvers *.markers *.unsigned *.order *~
clean:
make -C ( K D I R ) M = (KDIR) M= (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 ( M O D S R C D I R ) / (MOD_SRC_DIR)/ (MODSRCDIR)/(COMMON_DIR)/$${cpu}/ all
————————————————

                        版权声明:本文为博主原创文章,遵循 CC 4.0 BY-SA 版权协议,转载请附上原文出处链接和本声明。
  • 20
    点赞
  • 30
    收藏
    觉得还不错? 一键收藏
  • 打赏
    打赏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

草丛中的蝈蝈

您的鼓励是我最大的动力....

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值