**
在編譯kernel的時候,會編譯出乙個bzimage的檔案,據說這個是可以引導的檔案?
恩,關於這個問題,昨天我還真好好看了一下,發現還真是。玩了核心這麼多年,一直都以為是根目錄下的那個vmlinux是安裝時拷貝到/boot/目錄下的檔案,結果原來不是。真是慚愧慚愧。
我是從make install這個規則開始找下去的。
boot := arch/x86/boot
install:
$(q)$(make) $(build)=$(boot) $@
這個規則在arch/x86/makefile中,好奇為什麼沒有在根makefile裡找到。
那實際上真正執行的是在arch/x86/boot/makefile中這個規則
install:
sh $(srctree)/$(src)/install.sh $(kernelrelease) $(obj)/bzimage \
system.map "$(install_path)"
對應x86架構,在這個install.sh就是arch/x86/boot/install.sh。雖然指令碼中有幾種安裝核心的方式,不過我們只看其中一種也就能確認安裝在/boot/目錄下的是bzimage而不是vmlinux了。
cat $2 > $4/vmlinuz
所以說不看不知道,一看嚇一跳。以後不敢說自己懂核心了。
目標在**?
我們在核心編譯的小目標一文中也提到過,bzimage是x86平台下預設的目標之一。但是並沒有在根目錄的makefile中發現bzimage目標。 而在根目錄的makefile中的前面部分有
include $(srctree)/arch/$(srcarch)/makefile
這個是不同的arch會include不同的檔案,比如是x86的架構就會include arch/x86/makefile
開啟一看,果不其然
# default kernel to build
all: bzimage
好了,我們終於找到這個bzimage的target了,在x86平台它也是all的一部分。
來看看具體是什麼
生成規則
在arch/x86/makefile中,bzimage具體定義是這麼個樣子的。
# kbuild_image specify target image being built
kbuild_image := $(boot)/bzimage
bzimage: vmlinux
ifeq ($(config_x86_decoder_selftest),y)
$(q)$(make) $(build)=arch/x86/tools posttest
endif
$(q)$(make) $(build)=$(boot) $(kbuild_image)
$(q)mkdir -p $(objtree)/arch/$(uts_machine)/boot
$(q)ln -fsn ../../x86/boot/bzimage $(objtree)/arch/$(uts_machine)/boot/$@
又是一坨這麼長的,整的好生心煩。幸好,看到了乙個眼熟的$(make) (bu
ild)
=(build)=
(build
)=(boot) $(kbuild_image)。這個不是我們編譯具體目標的時候經常看到的麼?咱來展開看一眼:
make -f scripts/makefile.build obj=arch/x86/boot arch/x86/boot/bzimage
是不是覺得好像親切了一些?
對scripts/makefile.build檔案再補充一點,在該檔案的開頭處出了包含了scripts/kbuild.include檔案,還包含了乙個$(build-file)檔案。
先來看一下這個變數的定義:
#the filename kbuild has precedence over makefile
kbuild-dir := $(if $(filter /%,$(src)),$(src),$(srctree)/$(src))
kbuild-file := $(if $(wildcard $(kbuild-dir)/kbuild),$(kbuild-dir)/kbuild,$(kbuild-dir)/makefile)
include $(kbuild-file)
你猜到了什麼不? 沒猜到? 再看一眼上面的注釋?
對了,這個就是單個目錄下符合kbuild系統的規則檔案。
你還記得編譯乙個核心模組時候那個makefile中定義的obj-y, obj-m麼?為什麼我們在核心模組中的規則檔案只需要定義這幾個變數,就可以編譯出目標檔案和模組呢?原因就是在scripts/makefile.build中包含了目標目錄下的規則檔案。
不懂也沒關係,看多了日後自然知曉。
先看一下當前包含的檔案,這次包含的是arch/x86/boot/makefile。裡面有這麼一句。
quiet_cmd_image = build $@
cmd_image = $(obj)/tools/build $(obj)/setup.bin $(obj)/vmlinux.bin \
$(obj)/zoffset.h $@
$(obj)/bzimage: $(obj)/setup.bin $(obj)/vmlinux.bin $(obj)/tools/build force
$(call if_changed,image)
@echo 'kernel: $@ is ready' ' (#'`cat .version`')'
簡單明瞭,會心一笑。
所以最後的最後是通過tools/build這個使用者態工具生成bzimage檔案,而依賴的檔案是setup.bin和vmlinux.bin。
當然加上絕對路徑後,這幾個檔案分別是,
arch/x86/boot/tools/build
arch/x86/boot/setup.bin
arch/x86/boot/vmlinux.bin
arch/x86/boot/zoffset.h arch/x86/boot/bzimage
一張圖顯示依賴關係setup.bin vmlinux.bin
\ /
\ /
bzimage
拷貝setup.bindest = fopen(ar**[4], "w");
file = fopen(ar**[1], "r");
c = fread(buf, 1, sizeof(buf), file);
if (fwrite(buf, 1, i, dest) != i)
die("writing setup failed");
先開啟了bzimage,叫dest。
然後讀取setup.bin到buf
最後寫入bzimage
拷貝vmlinux.bin
fd = open(ar**[2], o_rdonly);
kernel = mmap(null, sz, prot_read, map_shared, fd, 0);
/* copy the kernel code */
crc = partial_crc32(kernel, sz, crc);
if (fwrite(kernel, 1, sz, dest) != sz)
die("writing kernel failed");
先開啟了vmlinux.bin
做了一下map
拷貝到了dest指向的bzimage
是不是也挺簡單的呢。
bzimage的兩個組成部分vmlinux.bin和setup.bin又是怎麼出現的呢?
主鍵生成方式
在做搭建ssh專案時,用hibernate反射機制生成pojo以及對映檔案。表主鍵選擇的是uuid,但是程式執行過程中,就報錯了。結果查資料才發現一些問題。大家平時多注意點。在hibernate2.1中,主鍵生成策略中uuid分為uuid.hex和uuid.string,但是從hibernate3....
GUID生成方式
uniqueidentifier guid 字段 在ms sql 資料庫中可以在建立表結構是指定字段型別為uniqueidentifier,並且其預設值可以使用newid 來生成唯一的guid 全域性唯一識別符號 使用newid生成的比較隨機,如果是sql 2005可以使用newsequential...
物件的生成方式
物件的生成方式 拷貝建構函式 用乙個已經存在的物件去初始化另乙個物件時,用到拷貝建構函式。如 class a a a1 a a2 a1 這裡就用到拷貝建構函式 另外 在傳入引數和return返回時,以傳值方式傳遞,需要呼叫拷貝建構函式。需要注意的兩種情況 1 a a1 a a2 a2 a1 並沒有用...