[Linux driver] Hello world编译过程解析

 虽然系统提供的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.chello.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'

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值