参考文章:Ubuntu 下构建内核源码树----------百度文库
http://blog.youkuaiyun.com/freedom2028/article/details/7879574 Ubuntu编译内核树
首先我实验的hello和scull模块都不需要建立内核源码树,只需系统自带的头文件就可。
ubuntu:10.04
1确认你当前使用ubuntu系统的内核版本
当模块代码要链接至不同版本的内核时,必须要做的就是对这个模块代码重新进行编译。这是因为模块对某一版本内核中定义的一些数据结构以及函数原型等都具有很强的信赖性,而模块所访问的内核接口因内核版本的不同而不同。所以在建立自己当前的内核树前一定要查看当前PC上使用的的linux内核版本,然后再建立针对此版本的内核树。如果版本不对会出现一些错误,如当前我的系统内核版本为:
2.6.32-21-generic
但是我用其它版本的内核源码来建立内核树,那么会导致在我当前内核版本(即2.6.32-21-generic下)执行insmod *.ko操作时会发生如下错误:
Error inserting './hello.ko': -1 Invalid module format
切记!~~~
2如在系统的Terminal中输入:
zhm@o_o:/lib/modules$ uname -r
响应:
2.6.32-21-generic //这是显示当前系统所使用的内核版本
3下载针对此版本的内核源码,在终端中输入:
zhm@o_o:/lib/modules$ apt-cache search linux-source (注意,此时不能以root身份操作)
响应:
linux-source - Linux kernel source with Ubuntu patches
linux-source-2.6.32 - Linux kernel source for version 2.6.32 with Ubuntu patches
紧接着下载此源码包即可:
zhm@o_o:/lib/modules$ sudo apt-get install linux-source-2.6.32
于是我们得到: linux-source-2.6.32.tar.bz2
4解压
将linux-source-2.6.32.tar.bz2 内核源码在/usr/src中解压:
zhm@o_o: /usr/src/$ sudo tar jxvf linux-source-2.6.32.tar.bz2
然后进入其目录
zhm@o_o:/usr/src$ cd linux-source-2.6.32
zhm@o_o:/usr/src/linux-source-2.6.32$
5配置编译内核
我采用的是最快速的配置(即默认)的方式:
zhm@o_o:/usr/src/linux-source-2.6.32$sudo make oldconfig
我用的 是 cp ../linux-headers-2.6.32-38-generic/.config .config
上面步骤完成后,开始进行make, 此步要花很长时间,你可以去干其它事情了,一般要1-2小时吧
zhm@o_o:/usr/src/linux-source-2.6.32$sudo make-j4
执行结束后会在当前文件夹下生成一个vmlinux的文件, 其属性为-rwxr-xr-x
然后编译模块:
zhm@o_o:/usr/src/linux-source-2.6.32$sudo make modules
最后一步,安装模块:
zhm@o_o:/usr/src/linux-source-2.6.32$sudo make modules_install
执行成功后,紧接着会在/lib/modules下生成一个2.6.32-21-generic文件夹,文件夹中含有build及source文件,这两个文件就是我们在编译模块时在Makefile中需要用到的,它们实际上是链接文件,指向我们在建立内核树时的那个目录:/usr/src//linux-source-2.6.32,实际上这个目录也就是我们要建立的内核树了,如下所示:
zhm@o_o:/lib/modules/2.6.32-21-generic$ ls -la
总用量 3712
drwxr-xr-x 3 root root 4096 2010-09-29 14:12 .
drwxr-xr-x 5 root root 4096 2010-09-29 14:09 ..
lrwxrwxrwx 1 root root 24 2010-09-29 14:09 b uild -> /usr/src/linux-source-2.6.32
drwxr-xr-x 9 root root 4096 2010-09-29 14:11 kernel
-rw-r--r-- 1 root root 599140 2010-09-29 14:12 modules.alias
-rw-r--r-- 1 root root 576280 2010-09-29 14:12 modules.alias.bin
-rw-r--r-- 1 root root 69 2010-09-29 14:12 modules.ccwmap
-rw-r--r-- 1 root root 269377 2010-09-29 14:12 modules.dep
-rw-r--r-- 1 root root 396085 2010-09-29 14:12 modules.dep.bin
-rw-r--r-- 1 root root 1405 2010-09-29 14:12 modules.ieee1394map
-rw-r--r-- 1 root root 218 2010-09-29 14:12 modules.inputmap
-rw-r--r-- 1 root root 24732 2010-09-29 14:12 modules.isapnpmap
-rw-r--r-- 1 root root 74 2010-09-29 14:12 modules.ofmap
-rw-r--r-- 1 root root 103687 2010-09-29 14:09 modules.order
-rw-r--r-- 1 root root 405322 2010-09-29 14:12 modules.pcimap
-rw-r--r-- 1 root root 1597 2010-09-29 14:12 modules.seriomap
-rw-r--r-- 1 root root 218944 2010-09-29 14:12 modules.symbols
-rw-r--r-- 1 root root 284287 2010-09-29 14:12 modules.symbols.bin
-rw-r--r-- 1 root root 870799 2010-09-29 14:12 modules.usbmap
l r wxrwxrwx 1 root root 24 2010-09-29 14:09 source -> /usr/src/linux-source-2.6.3 2
问题来了:我的/lib/modules下面有2.6.32-38-generic和2.6.32.63+drm33.26 两个文件夹经查看,2.6.32.63+drm33.26才是我刚建立的内核源码树,那2.6.32-38-generic一定是系统自带的头文件目录了,那么系统默认使用的还是2.6.32-38-generic,这个文件夹名称是在源码根目录下的Makefile里定义的,模块指定的目录在Makefile里KERNELDIR ?= /lib/modules/$(shell uname -r)/build定义其实对应的是系统默认使用的2.6.32-38-generic,所以不是我们编译的。
后面的操作就简单了,在Makefile文件中指定编译时内核树路径即可,下面为一段简单的Makefile源码:
# If KERNELRELEASE is defined, we've been invoked from the
# kernel build system and can use its language.
ifneq ($(KERNELRELEASE),)
obj-m := hello.o
# Otherwise we were called directly from the command
# line; invoke the kernel build system.
else
KERNELDIR ?= /lib/modules/$(shell uname -r)/build
PWD := $(shell pwd)
default:
$(MAKE) -C $(KERNELDIR) M=$(PWD) modules
endif
后面的事就简单了,写好模块代码,写好Makefile,直接在Terminal输make就可以编译成*.ko文件了。