内核目录树建立(完整版)
致读者:
很高兴和大家一起分享我的一些实践经历,下面我将要介绍给大家的是驱动程序以模块方式加载进内核开发环境的搭建,即内核目录树的建立;请读者注意当你想开始动手做时,请先了解一些内核驱动的基本知识,我在这里就不说了。同时要安装的内核源代码最好与你的linux内核版本相同,这样不会出现很多不必要的问题,要记住:“我们是做开发,而不是做环境”。
一、首先将源码包解压,如下:
[root@localhost /]# rpm -Uvh kernel-2.6.11-1.1369_FC4.src.rpm
这个命令将RPM内容写到路径/usr/src/redhat/SOURSE和/usr/src/redhat/SPECS
执行效果如下:
warning: kernel-2.6.11-1.1369_FC4.src.rpm: Header V3 DSA signature: NOKEY, key ID 4f2a6fd2
1:kernel ########################################### [100%]
二、build源码包
进入到如下目录:
# cd /usr/src/redhat/SPECS
[root@localhost SPECS]# pwd
/usr/src/redhat/SPECS
[root@localhost SPECS]# ls
kernel-2.6.spec
[root@localhost SPECS]#
然后执行:
#rpmbuild -bp --target i686 kernel-2.6.spec
这个命令将会把内核源码树放到如下目录,如下:[root@localhost linux-2.6.11]# pwd
/usr/src/redhat/BUILD/kernel-2.6.11/linux-2.6.11
注:再没有执行上面语句时,BUILD目录为空,执行后该目录下生成了kernel-2.6.11/linux-2.6.11,目录下内容如下:
[root@localhost linux-2.6.11]# ls
archDocumentationipcmmsecurity
configsdriverskernelnetsound
COPYINGfslibREADMEusr
CREDITSincludeMAINTAINERSREPORTING-BUGS
cryptoinitMakefilescripts
[root@localhost linux-2.6.11]#
三、配置内核
Fedora Core附带的内核配置文件在/usr/src/redhat/BUILD/kernel-2.6.11/linux-2.6.11/configs目录下
例如,i686 SMP配置文件被命名为configs/kernel-version-i686-smp.config。
源代码目录如下:
[root@localhost configs]# pwd
/usr/src/redhat/BUILD/kernel-2.6.11/linux-2.6.11/configs//配置文件目录
[root@localhost configs]# ls//内容如下:
kernel-2.6.11-i586.configkernel-2.6.11-i686-xen0.config
kernel-2.6.11-i686.configkernel-2.6.11-i686-xenU.config
kernel-2.6.11-i686-smp.config
[root@localhost configs]#
然后,使用下列命令来将需要的配置文件复制到合适的位置,用来编译:#cd /usr/src/redhat/BUILD/kernel-2.6.11/linux-2.6.11#cp configs/kernel-version-i686.config .config//记住要养成备份的好习惯!
上面我们选择了kernel-version-i686-smp.config这个配置文件,用户可以根据自己的需求来选择configs目录下的内核配置文件。
[root@localhost linux-2.6.11]# cp configs/kernel-2.6.11-i686-smp.config .config
cp:是否覆盖‘.config’? y
上面的命令执行以后会将linux-2.6.11目录下的.config文件覆盖。
如果你不是多处理器不要选择kernel-2.6.11-i686-smp.config,如果你选错了,在后面之安装驱动文件的时候会出现如下错误:
[root@localhost hello]# insmod hello.ko
insmod: error inserting 'hello.ko': -1 Invalid module format
然后查看日志信息:
[root@localhost hello]# cat /var/log/messages
Nov 22 18:27:10 localhost kernel: hello: version magic '2.6.11-1.1369_FC4SMP686 REGPARM 4KSTACKS gcc-4.0' should be '2.6.11-1.1369_FC4 686 REGPARM 4KSTACKS gcc-4.0'
也许当你看到这条信息的时候,你应该明白了,我不想读者跟我犯一样的错误。
接下来执行
#make menuconfig(图片无法显示,请查看附件)
然后选择Loadable module supportà,读者可以默认配置选项。同时读者也可以根据自己的需求来配置
注:第一项必须选择,因为它可以使驱动程序已模块的方式加载到内核中,同时读者还应该注意有几个选项后面有EXPERIMENTAL字样,说明不是很稳定,建议去掉。
配置好后就保存退出即可。
四、修改Makefile:每个内核的名字都包含了它的版本号,这也是uname -r命令显示的值。内核Makefile的前四行定义了内核的名字。为了保护官方的内核不被破坏,Makefile经过了修改,以生成一个与运行中的内核不同的名字。在一个模块插入运行中的内核前,这个模块必须针对运行中的内核进行编译。为此,您必须编辑内核的Makefile。例如,如果uname -r返回字符串2.6.11-1.1369_FC4,就将EXTRAVERSION定义从:EXTRAVERSION = -prep修改为:EXTRAVERSION = -1.1369_FC4
执行如下:
[root@localhost linux-2.6.11]#uname -r
2.6.11-1.1369_FC4
[root@localhost linux-2.6.11]#Vim Makefile
读者只需修改第四行即可。
五.编译内核:跟普遍的编译方法一样,执行如下:# make bzImage编译内核
最后结果:
。。。。。。。。。。。。。。。。。。。。。省略
HOSTCCarch/i386/boot/tools/build
BUILDarch/i386/boot/bzImage
Root device is (8, 3)
Boot sector 512 bytes.
Setup is 7290 bytes.
System is 1513 kB
Kernel: arch/i386/boot/bzImage is ready
[root@localhost linux-2.6.11]#
# make modules编译模块
安装模块,即编译.config文件中以M选项的代码
。。。。。。。。。。。。。。。。。。。。。。省略
CCsound/synth/snd-util-mem.mod.o
LD [M]sound/synth/snd-util-mem.ko
CCsound/usb/snd-usb-audio.mod.o
LD [M]sound/usb/snd-usb-audio.ko
CCsound/usb/snd-usb-lib.mod.o
LD [M]sound/usb/snd-usb-lib.ko
CCsound/usb/usx2y/snd-usb-usx2y.mod.o
LD [M]sound/usb/usx2y/snd-usb-usx2y.ko
[root@localhost linux-2.6.11]#
# make modules_install安装编译
编译结果:
。。。。。。。。。。。。。。。。。。。。。。。。。。。。。。省略
INSTALL sound/usb/snd-usb-audio.ko
INSTALL sound/usb/snd-usb-lib.ko
INSTALL sound/usb/usx2y/snd-usb-usx2y.ko
if [ -r System.map -a -x /sbin/depmod ]; then /sbin/depmod -ae -F System.map2.6.11-1.1369_FC4; fi
六、完成“内核树”的安装
目录“/usr/src/redhat/BUILD/kernel-2.6.11/kernel-2.6.11.686/”就是所谓的“内核代码树”但是“/lib/modules/2.6.11-1.1369_FC4/build”是个符号链接,也指向这个目录,所以这里也可以叫做“内核代码树”。
查看如下:
[root@localhost 2.6.11-1.1369_FC4]# pwd
/lib/modules/2.6.11-1.1369_FC4
[root@localhost 2.6.11-1.1369_FC4]# ll
总用量1048
lrwxrwxrwx1 root root48 11月22 15:10 build -> /usr/src/redhat/BUILD/kernel-2.6.11/linux-2.6.11
drwxr-xr-x9 root root4096 11月22 15:11 kernel
drwxr-xr-x2 root root4096 10月22 20:53 misc
-rw-r--r--1 root root 193905 11月22 15:13 modules.alias
-rw-r--r--1 root root69 11月22 15:13 modules.ccwmap
-rw-r--r--1 root root 233305 11月22 15:13 modules.dep
-rw-r--r--1 root root813 11月22 15:13 modules.ieee1394map
-rw-r--r--1 root root357 11月22 15:13 modules.inputmap
-rw-r--r--1 root root16284 11月22 15:13 modules.isapnpmap
-rw-r--r--1 root root 168540 11月22 15:13 modules.pcimap
-rw-r--r--1 root root89298 11月22 15:13 modules.symbols
-rw-r--r--1 root root 267526 11月22 15:13 modules.usbmap
lrwxrwxrwx1 root root48 11月22 15:10 source -> /usr/src/redhat/BUILD/kernel-2.6.11/linux-2.6.11
[root@localhost 2.6.11-1.1369_FC4]#
七、测试
首先编写hello.c源文件,如下:
1 #include
2 #include
3
4 MODULE_LICENSE("Dual BSD/GPL");
5
6 static int hello_init(void)
7 {
8printk(KERN_ALERT"Hello world\n");
9return 0;
10 }
11
12 static void hello_exit(void)
13 {
14printk(KERN_ALERT"Goodbye\n");
15 }
16
17 module_init(hello_init);
18 module_exit(hello_exit);
编写Makefile内容如下:
1 ifneq ($(KERNELRELEASE),)
2 obj-m:=hello.o
3 else
4KERNELDIR ?=/lib/modules/$(shell uname -r)/build
5PWD :=$(shell pwd)
6 default:
7$(MAKE) -C $(KERNELDIR) M=$(PWD) modules
8 endif
请注意Makefile的语法规则。
执行效果如下:
[root@localhost hello]# pwd
/hello
[root@localhost hello]# ls
hello.cMakefile
[root@localhost hello]#make
make -C /lib/modules/2.6.11-1.1369_FC4/build M=/hello modules
make[1]: Entering directory `/usr/src/redhat/BUILD/kernel-2.6.11/linux-2.6.11'
CC [M]/hello/hello.o
Building modules, stage 2.
MODPOST
CC/hello/hello.mod.o
LD [M]/hello/hello.ko
make[1]: Leaving directory `/usr/src/redhat/BUILD/kernel-2.6.11/linux-2.6.11'
[root@localhost hello]#
[root@localhost hello]# ls
hello.chello.kohello.mod.chello.mod.ohello.oMakefile
读者可以看到在hello目录下生成了hello.ko文件,这个就是2.6内核的驱动文件名。
八、安装编译好的hello驱动。
# insmod hello.ko应该可以看到返回的信息:Hello world然后再运行命令:# rmmod hello应该可以看到返回的信息:Goodbye
如果你没有看到,那么你可以看日志信息:
#cat /var/log/messages
总之:学习靠自己,继续努力吧!