如何将多个源文件编译为一个.ko

如何将多个源文件编译为一个.ko

分类: Linux driver & kernel 991人阅读 评论(0) 收藏 举报

陆陆续续也写了几个Linux内核模块了,但每次都是把代码写在一个源文件中,上次尝试了写在两个.c文件中,结果没有编译通过。 无奈之下,将其中一个.c文件重命名成.h文件,再include当另一个当中。但是,在.h文件中写函数的实现总感觉怪怪的。 今天查看了以下Kbuild的文档,有如下描述

[c-sharp] view plain copy
  1. If a kernel module is built from several source files, you specify  
  2.  that you want to build a module in the same way as above.  
  3.   
  4.  Kbuild needs to know which the parts that you want to build your  
  5.  module from, so you have to tell it by setting an  
  6.  $(<module_name>-objs) variable.  
  7.   
  8.  Example:  
  9.      #drivers/isdn/i4l/Makefile  
  10.      obj-$(CONFIG_ISDN) += isdn.o  
  11.      isdn-objs := isdn_net_lib.o isdn_v110.o isdn_common.o  
  12.   
  13.  In this example, the module name will be isdn.o. Kbuild will  
  14.  compile the objects listed in $(isdn-objs) and then run  
  15.  "$(LD) -r" on the list of these files to generate isdn.o.  

整理自己的源文件成两个.c文件(simpLB.c和sahu_lb_tools.c)、一个.h文件(sahu_lb.h)和Makefile文件。两个.c文件都包含了sahu_lb.h

按照Kbuild的文档所述,把Makefile改成如下内容:

[c-sharp] view plain copy
  1. obj-m +=simpLB.o   
  2. simpLB-objs:=sahu_lb_tools.o  
  3. all:  
  4.   make -C /lib/modules/`uname -r`/build M=`pwd`  
  5. clean:  
  6.   make -C /lib/modules/`uname -r`/build M=`pwd` clean  
  7. install:  
  8.   /sbin/insmod simpLB.ko  
  9. remove:  
  10.   /sbin/rmmod simpLB  

编译没有问题,但是安装后模块的功能没有实现,就连我在init_module()中打印的提示信息都没有。lsmod却有simpLB。

只好再上网查了查,发现如下文章:

http://www.linuxquestions.org/questions/programming-9/linking-multiple-files-kernel-module-programming-701735/

按照文章的的建议,我把Makefile修改成如下内容:

 

[c-sharp] view plain copy
  1. obj-m +=sahuLB.o   
  2. sahuLB-objs:=simpLB.o sahu_lb_tools.o  
  3. all:  
  4.   make -C /lib/modules/`uname -r`/build M=`pwd`  
  5. clean:  
  6.   make -C /lib/modules/`uname -r`/build M=`pwd` clean  
  7. install:  
  8.   /sbin/insmod sahuLB.ko  
  9. remove:  
  10.   /sbin/rmmod sahuLB 


----------------------------------

hell.ko的编译过程

1 源代码书写要保证正确,MODULE_LICENSE();是一条语句,后面要有分号;
2 static void hello_exit()的返回类型为void;
3 make M=`pwd` M参数后面不是单引号,而是斜点``;
4 -c 指定包含kernel顶级Makefile的源码目录;
5 源代码要执行make menuconfig生成默认配置,无须修改任何内容;
6 make menuconfig 的运行可能需要安装necurses-dev;
7 生成ko模块文件所使用的源码版本要和insmod的目标内核版本一致;
8 2.6个版本内核下载 http://www.kernel.org/pub/linux/kernel/v2.6/;
9 make编译可能提示没有modpost等脚本文件,可以从其它源码目录拷到当前使用源码目录下,或者利用当前源码目录下的c文件直接编译生成;
10 如果insmod过程中出错,可以使用dmesg | tail 命令查看系统日志
11 模块的编译和插入,对版本一致性要求很严格,如果编译依赖的内核源码版本和目标平台正在运行的内核版本不一致的话,很可能模块无法正常insert,出现诸如“-1 Invalid module format”或“no symbol version for module layout”的错误
所以编译过程中:
不是为正在运行的内核编译模块:
make -C <path-to-kernel> M='pwd'
为正在运行的内核编译模块:
make -C /lib/modules/'uname -r'/build M='pwd'

即可以保证insmod无误;


  • 0
    点赞
  • 1
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
多个源文件放在同一个编译模块中,需要进行以下步骤: 1. 创建一个头文件,其中包含所有源文件的函数原型和变量声明,以及必要的宏定义和类型定义。 2. 在每个源文件中,包含这个头文件。 3. 编译每个源文件,生成对应的目标文件。 4. 将所有目标文件链接在一起,生成最终的可执行文件或库文件。 具体实现方式如下: 1. 创建一个头文件(例如,mylib.h),包含所有源文件的函数原型和变量声明,以及必要的宏定义和类型定义。例如: ``` #ifndef MYLIB_H #define MYLIB_H // 函数原型和变量声明 int add(int a, int b); int sub(int a, int b); extern int global_var; #endif // MYLIB_H ``` 2. 在每个源文件中,包含这个头文件,并实现对应的函数和变量。例如,在 add.c 中实现 add 函数: ``` #include "mylib.h" int add(int a, int b) { return a + b; } ``` 在 sub.c 中实现 sub 函数: ``` #include "mylib.h" int sub(int a, int b) { return a - b; } ``` 在 global_var.c 中声明全局变量 global_var: ``` #include "mylib.h" int global_var = 0; ``` 3. 编译每个源文件,生成对应的目标文件。例如,在 Linux 系统下,可以使用以下命令: ``` gcc -c add.c gcc -c sub.c gcc -c global_var.c ``` 4. 将所有目标文件链接在一起,生成最终的可执行文件或库文件。例如,在 Linux 系统下,可以使用以下命令: ``` gcc add.o sub.o global_var.o -o mylib ``` 这样就可以将多个源文件放在同一个编译模块中了,可以方便地进行管理和维护。

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

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

余额充值