Linux内核模块(驱动)编译详解

本文主要说说如何编译自己开发的内核模块。由于驱动通常也被编译成内核模块,因此文章的内容也适用于驱动的编译。

由于在下能力相当有限,有不当之处,还望大家批评指正^_^


一、准备工作



准备工作如何做,这里就不详说了。

a) 首先,你要有一台PC(这不废话么^_^),装好了Linux。

b) 安装好GCC(这个指的是host gcc,用于编译生成运行于pc机程序的)、make、ncurses等工具。

c) 如果你是为当前PC机开发内核模块,那么准备工作就结束了。

如果你是为嵌入式系统Linux系统开发内核模块,则继续如下两步

d) 安装好交叉编译工具链。例如,你的目标单板CPU可能是arm或mips等cpu,则安装相应的交叉编译工具链。安装后,需要将工具链路径添加到PATH环境变量中。例如,你安装的是arm工具链,那么你在shell中执行类似如下的命令,假如有类似的输出,就说明安装好了。

[root@localhost linux-2.6.33.i686]# arm-linux-gcc  --version
arm-linux-gcc (Buildroot 2010.11) 4.3.5
Copyright (C) 2008 Free Software Foundation, Inc.
This is free software; see the source for copying conditions.  There is NO
warranty; not even for MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.


e) 下载所需的内核源码,配置好,并编译一次。

   如果您不熟悉如何配置编译内核,可以参考如下文章:

http://blog.csdn.net/crazycoder8848/article/details/44131735

    注意,内核源码必须先编译一次。否则,无法编译模块。


二、编译

编译模块,总得来说,有如下两种方法。

a)  独立编译

b)  将模块代码集成到内核源码包中,跟随Linux内核一块编译


由于涉及多种场景,因此下文分别进行介绍。

为了行文方便,这里假定我们要编译的模块名称叫hello,并且模块的C文件所在目录为/root/hello。


(1) 为当前的PC机编译模块,独立编译

首先,在/root/hello中建立一个Makefile。

如果模块只有一个.c文件,那么文件名必须是hello.c。

此时,Makefile内容超级简单,全部内容就如下一行:

obj-m := hello.o


如果模块由多个.c文件构成,例如,main.c,a.c,b.c。

此时,Makefile的全部内容如下:

obj-m := hello.o
hello-objs := main.o a.o b.o


为了适应更通用的情况,这里再对此makefile做点解释。

obj-m是个makefile变量,他的值可以是一串.o文件的表列。

列表中的每一项,代表一个模块。

其实,我们可以通过一个makefile编译出多个模块。

例如,假设hello目录下存放了多个模块的C文件,别是hello、hello2、hello3。

hello模块的构成:main.c  a.c  b.c

hello2模块的构成:main2.c  a2.c  b2.c

hello3模块的构成:hello3.c

此时,Makefile写成如下形式即可。

obj-m := hello.o hello2.o hello3.o
hello-objs := main.o a.o b.o
hello2-objs := main2.o a2.o b2.o


有了Makefile,就可以编译了。

不过,我们先要确定当前PC机的源码树安装路径。

注意,这个源码树,是为PC机安装Linux操作系统的时候安装上去的。

此源码树中,并不包含完整的内核源码,只是包含了大量的头文件,配置文件,以及编译内核模块所需的信息。

首先执行 uname -r 命令,得到当前PC机上运行的内核的版本号。

假设输出是:2.6.33.3-85.fc13.i686.PAE

那么内核源码树的路径就是

/lib/modules/2.6.33.3-85.fc13.i686.PAE/build

同时,可以得知当前PC机系统,所有模块都安装到如下路径中了。

/lib/modules/2.6.33.3-85.fc13.i686.PAE/kernel

那么,有了这些信息,就可以开始编译了。

a) 编译命令:

make -C  /lib/modules/2.6.33.3-85.fc13.i686.PAE/build   SUBDIRS=/root/hello   modules


b) 模块安装命令:(排版不当,导致命令换行了 ^_^)

make -C  /lib/modules/2.6.33.3-85.fc13.i686.PAE/build   SUBDIRS=/root/hello   INSTALL_MOD_DIR=kernel/drivers/net  modules_install

上述命令执行后,模块就被安装到/lib/modules/2.6.33.3-85.fc13.i686.PAE/kernel/drivers/net目录中去了。


c) 清除命令:

make -C  /lib/modules/2.6.33.3-85.fc13.i686.PAE/build   SUBDIRS=/root/hello  clean


最后,为了编译的方便,我们在/root/hello下增加一个easy_make,内容如下。


BASEDIR := /lib/modules/$(shell uname -r)
KERNEL_SRC_TREE := $(BASEDIR)/build
PWD :=$(shell pwd)
INSTALL_DIR := kernel/drivers/net

.PHONY: all
all: clean modules install

obj-m := hello.o hello2.o hello3.o

hello-objs := main.o a.o b.o
hello2-objs := main2.o a2.o b2.o

.PHONY:modules
modules:
$(MAKE) -C $(KERNEL_SRC_TREE) SUBDIRS=$(PWD) modules
@echo $(abc-y)


.PHONY:clean
clean:
$(MAKE) -C $(KERNEL_SRC_TREE) SUBDIRS=$(PWD) clean


.PHONY:install
install:
$(MAKE) -C $(KERNEL_SRC_TREE) SUBDIRS=$(PWD) INSTALL_MOD_DIR=$(INSTALL_DIR) modules_install


这样的话,我们以后只需要cd到/root/hello目录,简单的执行如下命令,就可以完成相应的操作了^_^

make  -f easy_make modules

make -f easy_make  install 

make -f easy_make  clean


(2) 将模块代码集成到内核源码包中,跟随Linux内核一块编译

未完......



郑重声明:本站内容如果来自互联网及其他传播媒体,其版权均属原媒体及文章作者所有。转载目的在于传递更多信息及用于网络分享,并不代表本站赞同其观点和对其真实性负责,也不构成任何其他建议。