虽然系统提供的makefile很智能地将hello.c最终编译成了hello.ko,但是我还是想知道系统的makefile到底干了些什么。
首先看编译驱动的目录,编译后多个四个文件:hello.ko, hello.mod.c, hello.mod.o, hello.o
hello.mod.c是一个C程序的源文件,查看其内容,似乎仅仅只是定义了两个全局的结构体变量。
我猜想:这个文件其实是驱动的版本信息,编译后的这些信息就好像元数据一样附加到ELF文件的.TEXT段,然后加载驱动的框架可以读取这些信息。原理应该是WINDOWS下的那种rc文件一样。
光看生成的文件还不够,修改了一下Makefile,把具体的执行信息都打印出来:
obj-m := hello.o
KERNEL_DIR := /lib/modules/$(shell uname -r)/build
PWD := $(shell pwd)
all:
make -C $(KERNEL_DIR) SUBDIRS=$(PWD) modules -n
clean:
rm *.o *.ko
在调用系统提供的makefile的时候,加上-n的参数。-n是指执行命令的时候将命令打印出来,但并不真正的执行。
修改好后执行make,果然打印了许许多多的命令出来。认真看产生的命令,发现居然在源码目录下创建了一个隐藏文件,有意思,于是执行:ll -a,将所有文件显示出来:
编译驱动后,不仅仅只多了四个文件,其实还产生了一个隐藏目录(.tmp_versions)和三个隐藏的文本文件(.hello.ko.cmd, .hello.mod.o.cmd, .hello.o.cmd)。
查看三个隐藏文件的内容,终于明白了系统的makefile执行的流程:
1、建立隐藏文件夹.tmp_versions,作为编译过程中的临时文件夹;
2、使用脚本程序,根据hello.c生成hello.mod.c,hello.mod.c其实是驱动需要的元数据;
3、使用GCC编译hello.mod.c,生成hello.mod.o,将编译的命令参数行写到 .hello.mod.o
4、使用GCC编译hello.c,生成hello.o,将编译的命令参数行写到 .hello.o.cmd
5、使用ld链接器链接hello.mod.o和hello.o,生成hello.ko,将命令参数行写到.hello.ko.cmd
6、删除中间生成的临时文件
下面是make的执行过程:
make -C /lib/modules/2.6.28-11-generic/build M=/home/ldd3/helloworld -n
make[1]: Entering directory `/usr/src/linux-headers-2.6.28-11-generic'
mkdir -p /home/ldd3/helloworld/.tmp_versions ; rm -f /home/ldd3/helloworld/.tmp_versions/*
test -e /usr/src/linux-headers-2.6.28-11-generic/Module.symvers || ( \
echo; \
echo " WARNING: Symbol version dump /usr/src/linux-headers-2.6.28-11-generic/Module.symvers"; \
echo " is missing; modules will have no dependencies and modversions."; \
echo )
make -f scripts/Makefile.build obj=/home/ldd3/helloworld
{ echo /home/ldd3/helloworld/hello.ko; echo /home/ldd3/helloworld/hello.o; } > /home/ldd3/helloworld/.tmp_versions/hello.mod
(cat /dev/null; echo kernel//home/ldd3/helloworld/hello.ko;) > /home/ldd3/helloworld/modules.order
:
echo ' Building modules, stage 2.';
make -f /usr/src/linux-headers-2.6.28-11-generic/scripts/Makefile.modpost
echo ' MODPOST 1 modules'; scripts/mod/modpost -m -a -i /usr/src/linux-headers-2.6.28-11-generic/Module.symvers -I /home/ldd3/helloworld/Module.symvers -o
/home/ldd3/helloworld/Module.symvers -S -K /usr/src/linux-headers-2.6.28-11-generic/Module.markers -M /home/ldd3/helloworld/Module.markers -w -s /home/ld
d3/helloworld/hello.o
set -e; echo ' CC /home/ldd3/helloworld/hello.mod.o'; gcc -Wp,-MD,/home/ldd3/helloworld/.hello.mod.o.d -nostdinc -isystem /usr/lib/gcc/i486-linux-gn
u/4.3.3/include -D__KERNEL__ -Iinclude -I/usr/src/linux-headers-2.6.28-11-generic/arch/x86/include -include include/linux/autoconf.h -Iubuntu/include -Wa
ll -Wundef -Wstrict-prototypes -Wno-trigraphs -fno-strict-aliasing -fno-common -Werror-implicit-function-declaration -O2 -m32 -msoft-float -mregparm=3 -freg
-struct-return -mpreferred-stack-boundary=2 -march=i586 -mtune=generic -Wa,-mtune=generic32 -ffreestanding -pipe -Wno-sign-compare -fno-asynchronous-unwind-
tables -mno-sse -mno-mmx -mno-sse2 -mno-3dnow -Iarch/x86/include/asm/mach-default -fno-stack-protector -fno-omit-frame-pointer -fno-optimize-sibling-calls -
Wdeclaration-after-statement -Wno-pointer-sign -fwrapv -D"KBUILD_STR(s)=#s" -D"KBUILD_BASENAME=KBUILD_STR(hello.mod)" -D"KBUILD_MODNAME=KBUILD_STR(hello)"
-DMODULE -c -o /home/ldd3/helloworld/hello.mod.o /home/ldd3/helloworld/hello.mod.c; scripts/basic/fixdep /home/ldd3/helloworld/.hello.mod.o.d /home/ldd3/h
elloworld/hello.mod.o 'gcc -Wp,-MD,/home/ldd3/helloworld/.hello.mod.o.d -nostdinc -isystem /usr/lib/gcc/i486-linux-gnu/4.3.3/include -D__KERNEL__ -Iinclud
e -I/usr/src/linux-headers-2.6.28-11-generic/arch/x86/include -include include/linux/autoconf.h -Iubuntu/include -Wall -Wundef -Wstrict-prototypes -Wno-tr
igraphs -fno-strict-aliasing -fno-common -Werror-implicit-function-declaration -O2 -m32 -msoft-float -mregparm=3 -freg-struct-return -mpreferred-stack-bound
ary=2 -march=i586 -mtune=generic -Wa,-mtune=generic32 -ffreestanding -pipe -Wno-sign-compare -fno-asynchronous-unwind-tables -mno-sse -mno-mmx -mno-sse2 -mn
o-3dnow -Iarch/x86/include/asm/mach-default -fno-stack-protector -fno-omit-frame-pointer -fno-optimize-sibling-calls -Wdeclaration-after-statement -Wno-poin
ter-sign -fwrapv -D"KBUILD_STR(s)=\#s" -D"KBUILD_BASENAME=KBUILD_STR(hello.mod)" -D"KBUILD_MODNAME=KBUILD_STR(hello)" -DMODULE -c -o /home/ldd3/helloworl
d/hello.mod.o /home/ldd3/helloworld/hello.mod.c' > /home/ldd3/helloworld/.hello.mod.o.tmp; rm -f /home/ldd3/helloworld/.hello.mod.o.d; mv -f /home/ldd3/hell
oworld/.hello.mod.o.tmp /home/ldd3/helloworld/.hello.mod.o.cmd
set -e; echo ' LD [M] /home/ldd3/helloworld/hello.ko'; ld -r -m elf_i386 --build-id -o /home/ldd3/helloworld/hello.ko /home/ldd3/helloworld/hello.o /hom
e/ldd3/helloworld/hello.mod.o; echo 'cmd_/home/ldd3/helloworld/hello.ko := ld -r -m elf_i386 --build-id -o /home/ldd3/helloworld/hello.ko /home/ldd3/hellow
orld/hello.o /home/ldd3/helloworld/hello.mod.o' > /home/ldd3/helloworld/.hello.ko.cmd
make[1]: Leaving directory `/usr/src/linux-headers-2.6.28-11-generic'