欢迎光临散文网 会员登陆 & 注册

Linux内核模块如何编译?(有这篇文就足够~)

2022-06-10 17:01 作者:补给站Linux内核  | 我要投稿

本文主要介绍如何在内核外编译内核模块,

即: how to build an out-of-tree kernel module.

1. 代码hello.c

2. Makefile

3. 编译测试

make sudo insmod hello.ko dmesg sudo rmmod hello

  • 内核信息如下:

[156596.317933] hello world. [156604.933930] hello exit!


【文章福利】小编推荐自己的Linux内核技术交流群:【891587639】整理了一些个人觉得比较好的学习书籍、视频资料共享在群文件里面,有需要的可以自行添加哦!!!(含视频教程、电子书、实战项目及代码)     


4. Makefile分析

4.1 多个源文件

  • 如果你有一个模块名为 module.ko, 是来自 多个源文件( 姑且称之为, file1.c 和 file2.c ), 正确的书写应当是:

obj-m := module.o module-objs := file1.o file2.o



4.2 clean

rm -f *.ko *.o *.mod.o *.mod.c *.symvers *.order

  • 可以换成:

make -C $(KDIR) M=$(PWD) clean


4.3 KERNELRELEASE

  • 这个 makefile 在一次典型的建立中要被读 2 次。


  • KERNELRELEASE是在内核源码的顶层Makefile中定义的一个变量,在第一次(刚开始)读取执行此Makefile时,KERNELRELEASE没有被定义(为空),所以make将读取执行else之后的内容。如果make的目标是clean,直接执行clean操作,然后结束。当make的目标为all时,-C(KDIR)指明跳转到内核源码目录下读取那里的Makefile,M=(PWD)表明然后返回到当前目录继续读入、执行当前的Makefile。当从内核源码目录返回时,KERNELRELEASE已被被定义,kbuild也被启动去解析kbuild语法的语句,make将继续读取else之前的内容(指 obj-m :=hello.o)。else之前的内容为kbuild语法的语句,指明模块源码中各文件的依赖关系,以及要生成的目标模块名。

4.4 obj-m

obj-m :=hello.o表示编译连接后将生成hello.o模块。 module-objs := file1.o file2.o file3.o表示module.o 由file1.o,file2.o与file3.o 链接生成。

  • 在modules.txt中提到:

obj-m := <module_name>.o


The kbuild system will build <module_name>.o from <module_name>.c, and, after linking, will result in the kernel module <module_name>.ko. The above line can be put in either a "Kbuild" file or a "Makefile." When the module is built from multiple sources, an additional line is needed listing the files: <module_name>-y := <src1>.o <src2>.o ...

4.5 $(KDIR)

/lib/modules/$(shell uname -r)/build 是内核top makefile所在路径。 $(shell uname -r):是调用shell命令显示内核版本,在我系统上是4.4.0-109-generic

4.6 kbuild makefile

  • Kbuild系统使用Kbuild Makefile来编译内核或模块。当Kernel Makefile被解析完成后,Kbuild会读取相关的Kbuild Makefile进行内核或模块的编译。Kbuild Makefile有特定的语法指定哪些编译进内核中、哪些编译为模块、及对应的源文件是什么等。内核及驱动开发人员需要编写这个Kbuild Makefile文件。

  • 目标定义是Kbuild Makefile的主要部分,也是核心部分。主要是定义了要编译的文件,所有的选项,以及到哪些子目录去执行递归操作。 最简单的Kbuild makefile 只包含一行:

例子: obj-y += foo.o

  • 该例子告诉Kbuild在这目录里,有一个名为foo.o的目标文件。foo.o将从foo.c 或foo.S文件编译得到。 如果foo.o要编译成一模块,那就要用obj-m了。所采用的形式如下:

例子: obj-$(CONFIG_FOO) += foo.o

  • $(CONFIG_FOO)可以为y(编译进内核) 或m(编译成模块)。如果CONFIG_FOO不是y 和m,那么该文件就不会被编译联接了。

4.7 -C $KDIR and M=$PWD

  • 以下在内核文档/kbuild/modules.txt中有介绍。

-C $KDIR The directory where the kernel source is located. "make" will actually change to the specified directory when executing and will change back when finished. M=$PWD Informs kbuild that an external module is being built. The value given to "M" is the absolute path of the directory where the external module (kbuild file) is located.

4.8 modules

When building an external module, only a subset of the "make" targets are available. make -C $KDIR M=$PWD [target] The default will build the module(s) located in the current directory, so a target does not need to be specified. All output files will also be generated in this directory. No attempts are made to update the kernel source, and it is a precondition that a successful "make" has been executed for the kernel. modules The default target for external modules. It has the same functionality as if no target was specified. See description above. modules_install Install the external module(s). The default location is /lib/modules/<kernel_release>/extra/, but a prefix may be added with INSTALL_MOD_PATH (discussed in section 5). clean Remove all generated files in the module directory only. help List the available targets for external modules.




Linux内核模块如何编译?(有这篇文就足够~)的评论 (共 条)

分享到微博请遵守国家法律