您的位置:首页 > 运维架构 > Linux

Linux内核---9.prepare0流程

2016-07-02 14:36 781 查看
linux-2.6.30.4/Makefile中,prepare0的依赖执行完之后,执行:

   make -f scripts/Makefile.build obj=.

#执行scripts/Makefile的__build目标,此处只执行always依赖,(KBUILD_BUILTIN=1,但是$(builtin-target) $(lib-target) $(extra-y)都为空,KBUILD_MODULES=0)

always=./include/linux/bounds.h ./include/asm/asm-offsets.h 

__build: ./include/linux/bounds.h ./include/asm/asm-offsets.h 

    :

./include/linux/bounds.h 与./include/asm/asm-offsets.h 这两个依赖的处理过程基本相似。

下面只分析./include/linux/bounds.h的过程。

点击(此处)折叠或打开

linux-2.6.30.4/Kbuild

 11 bounds-file := include/linux/bounds.h

 38 $(obj)/$(bounds-file): kernel/bounds.s
Kbuild

 39 
$(Q)mkdir -p $(dir
$@)

 40 
$(call cmd,bounds)

 34 kernel/bounds.s: kernel/bounds.c
FORCE

 35 
$(Q)mkdir -p $(dir
$@)

 36 
$(call if_changed_dep,cc_s_c)

   目标include/linux/bounds.h在linux-2.6.30.4/Kbuild中,它的执行流程如下:
1. L34 mkdir -p kernel
2. L36 $(call if_changed_dep, cc_s_c),如果kernel/bounds.c有更新,则重新编译kernel/bounds.c,并将编译命令显示在终端,最后将编译命令写到文件.bounds.s.cmd.o中
3. kernel/bounds.s依赖完成之后,执行include/linux/bounds.h目标
4. L39 mkdir -p include/linux
5. $(call cmd, bounds) ,生成include/linux/bounds.h头文件
下面分析一下第2步: $(call if_changed_dep,cc_s_c)

点击(此处)折叠或打开

linux-2.6.30.4/scripts/Kbuild.include

197 # Execute the command and also postprocess generated .d dependencies file.

198 if_changed_dep = $(if $(strip
$(any-prereq) $(arg-check) ), \

199 @set -e; \

200 $(echo-cmd) $(cmd_$(1)); \

201 scripts/basic/fixdep $(depfile) $@ '$(make-cmd)' > $(dot-target).tmp;\

202 rm -f $(depfile); \

203 mv -f $(dot-target).tmp
$(dot-target).cmd)

2.1 $(if $(strip $(any-prereq) $(arg-check) ) #如果目标有更新,则执行条件后面的东东

2.2 $(echo-cmd) 打印编译命令

2.3 $(cmd_cc_s_c) 在linux-2.6.30.4/scripts/Makefile.build中定义cmd_cc_s_c = $(CC) $(c_flags) -fverbose-asm
-S -o $@ $<,这里面有-S,是将c文件转为.s文件,也就是常说的汇编阶段。

2.4 将kernel/bounds.c的汇编和编译所需的头文件统统写进文件kernel/.bounds.s.d.tmp中

2.5 删除kernel/.bounds.s.d 

2.6 将kernel/.bounds.s.d.tmp 重命名为kernel/.bounds.s.d.cmd

2.1.1 突然想起小学时写作文老师说的总分方式:

点击(此处)折叠或打开

linux-2.6.30.4/scripts/Kbuild.include 

L189 any-prereq = $(filter-out
$(PHONY),$?) $(filter-out
$(PHONY) $(wildcard $^),$^)

     #检查目标代码是否有更新,如果有更新返回值不为空

177 arg-check = $(strip $(filter-out
$(cmd_$(1)), $(cmd_$@)) \

178 $(filter-out $(cmd_$@), $(cmd_$(1))) )

    #检查参数是否改变,若有改变,返回值不为空

2.2.1 $(echo-cmd)
打印编译命令

点击(此处)折叠或打开

linux-2.6.30.4/scripts/Kbuild.include

  24 # Escape single quote for use in echo statements

  25 escsq = $(subst $(squote),'\$(squote)',$1)

155 # Short version is used, if $(quiet) equals `quiet_', otherwise full one.

156 echo-cmd = $(if $($(quiet)cmd_$(1)),\

157     echo '  $(call escsq,$($(quiet)cmd_$(1)))$(echo-why)';)

linux-2.6.30.4/Makefile控制quiet的值,此处为空,1是指cc_s_c,如果cmd_cc_s_c执行成功,就打印$(cmd_cc_s_c)即具体的编译过程到命令行。

这地方有点想不明白,if后面 $(cmd_cc_s_c)要执行一次,$(echo-cmd)执行完后又有一个$(cmd_$(1)),难不成$(cmd_cc_s_c)要执行两次?

噢,想错了!下面是GNU
`make'对if的说明 “$(if condition,then-part[,else-part]) The first argument, condition,
first has all preceding and trailing whitespace stripped, then is expanded. If it expands to any non-empty string, then the condition is considered to be true. If it expands to an empty string, the condition is considered to be false.” 对于第一个参数:condition,首先去掉前面和尾部的空格,然后把条件语句展开。如果展开后是一个不为空的string,那么这个条件就被认为是true,反之是一个空string,
认为是false.

2.3.1 $(cmd_cc_s_c) 即$(CC)
$(c_flags) -fverbose-asm -S -o $@ $<,具体的编译过程

2.4.1 scripts/basic/fixdep这个东东在make
menuconfig/silentconfig中己经生成,具体是什么作用没有看,感觉是把.c文件需要的include重定向到另一个文件中。

5.1 $(call cmd, bounds)的过程

点击(此处)折叠或打开

linux-2.6.30.4/scripts/Kbuild.include

154 # echo command.

155 # Short version is used,if $(quiet)
equals `quiet_', otherwise full one.

156 echo-cmd
= $(if $($(quiet)cmd_$(1)),\

157 echo ' $(call escsq,$($(quiet)cmd_$(1)))$(echo-why)';)

158

159 # printing commands

160 cmd = @$(echo-cmd)
$(cmd_$(1))

cmd= @$(echo-cmd)
$(cmd_$(1))
先是打印命令这个,然后执行$(cmd_bounds)

点击(此处)折叠或打开

 linux-2.6.30.4/Kbuild 

 17 define cmd_bounds

 18 (set -e; \

 19 echo "#ifndef __LINUX_BOUNDS_H__"; \

 20 echo "#define __LINUX_BOUNDS_H__"; \

 21 echo "/*"; \

 22 echo " * DO NOT MODIFY."; \

 23 echo " *"; \

 24 echo " * This file was generated by Kbuild"; \

 25 echo " *"; \

 26 echo " */"; \

 27 echo ""; \

 28 sed -ne $(sed-y) $<; \

 29 echo ""; \

 30 echo "#endif" ) > $@

 31 endef

$@ 是 include/linux/bounds.h

$< 是 kernel/bounds.s 

这个宏简单一点就是: echo "something" > include/linux/bounds.h,将一些文本写入到include/linux/bounds.h中

点击(此处)折叠或打开

linux-2.6.30.4/Kbuild 

 54 define sed-y

 55 "/^->/{s:->#\(.*\):/* \1 */:; \

 56 s:^->\([^ ]*\) [\$$#]*\([^ ]*\) \(.*\):#define \1 \2 /* \3 */:; \

 57 s:->::; p;}"

 58 endef

 sed将kernel/bounds.s中以->开头的行进行处理,将行

->NR_PAGEFLAGS #21 __NR_PAGEFLAGS   @           替换为

#define NR_PAGEFLAGS 21 /* __NR_PAGEFLAGS   @ */
内容来自用户分享和网络整理,不保证内容的准确性,如有侵权内容,可联系管理员处理 点击这里给我发消息
标签: