日韩性视频-久久久蜜桃-www中文字幕-在线中文字幕av-亚洲欧美一区二区三区四区-撸久久-香蕉视频一区-久久无码精品丰满人妻-国产高潮av-激情福利社-日韩av网址大全-国产精品久久999-日本五十路在线-性欧美在线-久久99精品波多结衣一区-男女午夜免费视频-黑人极品ⅴideos精品欧美棵-人人妻人人澡人人爽精品欧美一区-日韩一区在线看-欧美a级在线免费观看

歡迎訪問 生活随笔!

生活随笔

當(dāng)前位置: 首頁 > 运维知识 > linux >内容正文

linux

arm-linux内核编译过程小结

發(fā)布時間:2025/4/16 linux 27 豆豆
生活随笔 收集整理的這篇文章主要介紹了 arm-linux内核编译过程小结 小編覺得挺不錯的,現(xiàn)在分享給大家,幫大家做個參考.

轉(zhuǎn)自:https://blog.csdn.net/lidan113lidan/article/details/44981829?spm=1001.2014.3001.5501

記在前面的雜七雜八

  • 內(nèi)核的生成,實際上最終的目的是生成一個binary文件zImage,大小2-5MB的數(shù)量級。
  • 用戶可以從kernel.org得到的tar.gz格式的內(nèi)核源代碼,此代碼解壓后,就會生成初始狀態(tài)的內(nèi)核源代碼樹,這種狀態(tài)稱為內(nèi)核的初始狀態(tài)。
  • 通過make mrproper/make distclean等指令,可以使內(nèi)核恢復(fù)到剛解壓的狀態(tài)。其中make mrproper只清除包括.config文件在內(nèi)的,為內(nèi)核編譯及連接而生成的諸多配置文件。distclean對象執(zhí)行mrproper命令,清除內(nèi)核編譯后生成的所有對象文件,備份文件等。
  • 如果將初始化狀態(tài)的內(nèi)核直接編譯,雖然能生成vmlinux,但大多數(shù)情況下會引起內(nèi)核嚴重錯誤(kernel panic)。構(gòu)建內(nèi)核前,需要執(zhí)行的最重要,最需謹慎處理的部分是內(nèi)核配置(kernel configureation)過程。內(nèi)核配置過程也是適當(dāng)選擇與自身相吻合的各種內(nèi)核要素的過程。
  • 內(nèi)核的配置可以用xconfig,menuconfig,gconfig等,最終都是會執(zhí)行一個二進制文件,如menuconfig最終執(zhí)行的是mconf,這個程序在./script/kconfig/目錄下。
  • 在構(gòu)建內(nèi)核時,各個*.o的目錄下都有一個.*.cmd,這個文件是記錄這個.o最終執(zhí)行的編譯命令的,如vmlinux.cmd和.vmlinux.o.cmd。
  • 一句make一般來說,默認的目標有兩個,一個是vmlinux,一個是zImage
  • 通過emulator啟動goldfish的時候,實際上啟動的是zImage,這貨才2.5MB左右,啟動命令如下:

    emulator -show-kernel -kernel /mnt/VMDisk1/kernel/goldfish/arch/arm/boot/zImage -avd test -qemu -s
    • 1
    • 1
  • 在圖形化界面下,內(nèi)核的配置也會有很多很多問題,一般每個系統(tǒng)均提供自定義配置文件,這些配置文件都是與具體芯片相關(guān)的(Soc, System on Chip),如下:

  • tigger@ubuntu:/mnt/VMDisk1/kernel/goldfish$ cd arch/ alpha/ blackfin/ frv/ ia64/ microblaze/ openrisc/ s390/ sparc/ unicore32/ arm/ c6x/ h8300/ m32r/ mips/ parisc/ score/ tile/ x86/ avr32/ cris/ hexagon/ m68k/ mn10300/ powerpc/ sh/ um/ xtensa/ tigger@ubuntu:/mnt/VMDisk1/kernel/goldfish/arch/arm/configs$ ll total 632 drwxr-xr-x 2 tigger tigger 4096 2014-10-14 20:09 ./ drwxr-xr-x 88 tigger tigger 4096 2014-11-01 02:28 ../ -rw-r--r-- 1 tigger tigger 1998 2014-10-11 02:28 acs5k_defconfig -rw-r--r-- 1 tigger tigger 2011 2014-10-11 02:28 acs5k_tiny_defconfig -rw-r--r-- 1 tigger tigger 2509 2014-10-14 20:09 afeb9260_defconfig -rw-r--r-- 1 tigger tigger 2241 2014-10-11 02:28 ag5evm_defconfig -rw-r--r-- 1 tigger tigger 2617 2014-10-11 02:28 am200epdkit_defconfig ......
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10
    • 11
    • 12
    • 13
    • 14
    • 15
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10
    • 11
    • 12
    • 13
    • 14
    • 15

    內(nèi)核的構(gòu)建

    • 如想使用goldfish的配置,可以:
    //根據(jù)goldfish_armv7_defconfig生成.config文件make goldfish_armv7_defconfig//調(diào)整一些具體細節(jié)項make menuconfig//然后就可以編譯了make
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • .config文件是構(gòu)建內(nèi)核所需的內(nèi)核配置目錄,它是在CONFIG_XXX變量中用y,n,m三個狀態(tài)進行配置的目錄,這種形態(tài)的內(nèi)核配置系統(tǒng)叫做kconfig。根據(jù)kconfig提供的三個狀態(tài)(y,n,m)決定是否構(gòu)建內(nèi)核相應(yīng)的模塊(Kconfig系統(tǒng)中y,n,m只是bool類型的配置選項,實際上.config中可能有hex/int/bool/tristate/string這多種類型的選項)。

      • 狀態(tài)為y時:相應(yīng)的二進制文件,與vmlinux鏈接。
      • 狀態(tài)為m時:不會和vmlinux鏈接,但作為模塊執(zhí)行編譯。
      • 狀態(tài)為n時:不編譯。
    • mconf通過.config配置文件,生成autoconf.h頭文件

    tigger@ubuntu:/mnt/VMDisk1/kernel/goldfish$ find ./ -name autoconf.h ./include/linux/autoconf.h ./include/generated/autoconf.h
    • 1
    • 2
    • 3
    • 1
    • 2
    • 3

    這兩個文件是一樣的,也不知道誰復(fù)制的誰,大體看一下文件內(nèi)容:

    #define CONFIG_RING_BUFFER 1 #define CONFIG_NF_CONNTRACK_H323 1 #define CONFIG_KERNEL_GZIP 1 #define CONFIG_INPUT_KEYBOARD 1 #define CONFIG_IP_NF_TARGET_REDIRECT 1 #define CONFIG_CRC32 1 #define CONFIG_NF_NAT_PROTO_SCTP 1 #define CONFIG_HAVE_AOUT 1 #define CONFIG_VFP 1 #define CONFIG_AEABI 1 #define CONFIG_FB_TILEBLITTING 1 #define CONFIG_HIGH_RES_TIMERS 1 #define CONFIG_BLK_DEV_DM 1 #define CONFIG_VLAN_8021Q 1
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10
    • 11
    • 12
    • 13
    • 14
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10
    • 11
    • 12
    • 13
    • 14

    可以發(fā)現(xiàn),在.config中定義的的宏,在預(yù)處理階段被處理成了各種#define語句。

    • 利用kconfig完成內(nèi)核配置,準備好.config文件后,即可構(gòu)建內(nèi)核。構(gòu)建內(nèi)核是指,編譯內(nèi)核,鏈接各個二進制文件,最終生成一個二進制文件zImage的一系列過程。

    • 從linux2.6開始,內(nèi)核采用kbuild系統(tǒng)來進行編譯了,kbuild是指上是一堆腳本的組合。

    linux內(nèi)核Makefile分類:?
    * Kernel Makefile: 位于內(nèi)核源代碼的頂層目錄,也叫Top Makefile。主要用于指定編譯內(nèi)核的目標文件(vmlinux)和模塊。在編譯內(nèi)核或模塊時,這個文件會被首先讀取,并根據(jù)內(nèi)容設(shè)置環(huán)境變量。?
    * kbuild Makefile: kbuild系統(tǒng)使用kbuild Makefile來編譯內(nèi)核或模塊,Kbuild Makefile指定哪些編譯近內(nèi)核,哪些編譯為模塊。?
    * arch Makefile: 位于./arch/$(ARCH)/Makefile,是系統(tǒng)對應(yīng)平臺的Makefile。top makefile會包含這個文件來指定平臺相關(guān)信息,只有平臺開發(fā)人員需要關(guān)心這個文件。


    vmlinux的生成

    編譯后,vmlinux是在內(nèi)核目錄樹的根目錄下生成的一個ELF文件,這里以goldfish下執(zhí)行make為例,查看vmlinux的生成。 當(dāng)執(zhí)行make命令的時候,會先掃描內(nèi)核的根目錄的Makefile:

    ##(后續(xù)只列舉關(guān)鍵內(nèi)容),./Makefile ##.PHONY: $(PHONY)是在Makefile最后定義的, .PHONY是將一個目標聲明為偽目標, ##這樣make在執(zhí)行規(guī)則時不會試圖去查找隱含規(guī)則來創(chuàng)建他(簡單理解不會把_all當(dāng) ##成一個文件,不會存在如果當(dāng)前目錄存在_all這個文件,而文件不更新,系統(tǒng)不能編譯的問題) ##所有這樣的文件都加到了.PHONY里面。 PHONY := _all ##_all是編譯的默認目標,就是make指令的默認目標 _all: ifeq ($(KBUILD_EXTMOD),) ##如果沒指定編譯模塊 _all: all else ##如果指定是編譯模塊 _all: modules endif #如果沒指定編譯模塊,則這里最終編譯的就是vmlinux #(注:在體系結(jié)構(gòu)相關(guān)的makefile中一般還有一個all,即zImage) all: vmlinux vmlinux: $(vmlinux-lds) $(vmlinux-init) $(vmlinux-main) vmlinux.o $(kallsyms.o) FORCE##vmlinux-modpost不存在,這里好像是忽略了??$(call vmlinux-modpost)##如果if_changed_rule成立則執(zhí)行rule_vmlinux__$(call if_changed_rule,vmlinux__)##刪除.old_version$(Q)rm -f .old_version
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10
    • 11
    • 12
    • 13
    • 14
    • 15
    • 16
    • 17
    • 18
    • 19
    • 20
    • 21
    • 22
    • 23
    • 24
    • 25
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10
    • 11
    • 12
    • 13
    • 14
    • 15
    • 16
    • 17
    • 18
    • 19
    • 20
    • 21
    • 22
    • 23
    • 24
    • 25

    后續(xù)會分析其中的各個目標

    目標文件 vmlinux.o

    vmlinux.o是沒有去除符號表的可執(zhí)行文件,最終生成的vmlinux為真正的內(nèi)核鏡像

    -rwxr-xr-x 1 tigger tigger 61M 2014-12-22 01:21 vmlinux* -rw-r--r-- 1 tigger tigger 109M 2014-12-22 01:21 vmlinux.o
    • 1
    • 2
    • 1
    • 2

    目標文件 vmlinux.lds

    vmlinux.lds是一個鏈接腳本,是給ld鏈接器使用的。一般來說,普通程序是不需要指定linker script的,也不需要關(guān)心各個section的具體位置。當(dāng)程序執(zhí)行時,kernel中的ELF Loader會根據(jù)ELF文件頭解析可執(zhí)行文件的各個section,并把他們映射到虛擬地址空間。然而,內(nèi)核啟動時,必須首先確定各個section的具體位置,這就是vmlinux.lds的作用。這個文件必然是體系結(jié)構(gòu)相關(guān)的,在arm中有兩個連接腳本分別位于:?
    ./arch/arm/kernel/vmlinux.lds(這個是給vmlinux編譯用的連接腳本,就是這里面的vmlinux.lds)?
    ./arch/arm/boot/compressed/vmlinux.lds(這個是給zImage編譯時候用的連接腳本)

    目標文件 kallsyms.o

    在2.6內(nèi)核中,為了更好的調(diào)試內(nèi)核,引入了kallsyms機制。kallsyms把內(nèi)核中用到的所有函數(shù)地址和名稱鏈接到內(nèi)核文件,當(dāng)內(nèi)核啟動后,同時加載到內(nèi)存中。當(dāng)發(fā)生oops時候,內(nèi)核就會?
    解析eip位于哪個函數(shù)中,然后打印出backtrace信息。內(nèi)核編譯的最后,make會執(zhí)行:nm -n vmlinux|scripts/kallsyms,其中:?
    1. nm -n vmlinux負責(zé)生成所有的內(nèi)核符號并按地址排序?
    2. scripts/kallsyms負責(zé)處理這個列表,并生成需要的鏈接文件tmp_kallsyms%.s?
    也就是說kallsyms實際上是內(nèi)核編譯完了之后,vmlinux中通過nm命令生成的,所以所有符號地址都包括了,實際上是和System.map是一樣的。?
    而且kallsyms中所有函數(shù)的地址,是放在一個全局數(shù)組kallsyms_addresses[]中的,如下:

    kallsyms_addresses:PTR _text + 0x180PTR _text + 0x180PTR _text + 0x180PTR _text + 0x194PTR _text + 0x360PTR _text + 0x374PTR _text + 0x484PTR _text + 0x594PTR _text + 0x5f4PTR _text + 0x5f8PTR _text + 0x60cPTR _text + 0x624
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10
    • 11
    • 12
    • 13
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10
    • 11
    • 12
    • 13
    kallsyms_addresses中的每一個表項,都在重定位表中有記錄,如果內(nèi)核發(fā)生了重定位,那么kallsyms中的內(nèi)容也會跟著修改,所以cat /proc/kallsyms的時候總是看到的是真正的函數(shù)地址。

    kallsyms的整個符號表,最終都會放在kallsyms.o文件中。

    #kallsyms也是最終依賴一個文件,這個是.tmp_kallsymsX.o kallsyms.o := .tmp_kallsyms$(last_kallsyms).o
    • 1
    • 2
    • 1
    • 2

    目標 vmlinux-init

    #./Makefile vmlinux-init := $(head-y) $(init-y)
    • 1
    • 2
    • 1
    • 2
    • head-y
    #./Makefile #head-y定義在具體體系結(jié)構(gòu)的makefile中,這句include會載入head-y的定義 include $(srctree)/arch/$(SRCARCH)/Makefile
    • 1
    • 2
    • 3
    • 1
    • 2
    • 3
    #./arch/arm/Makefile #這里的MMUEXT應(yīng)該是是否開啟mmu的意思,如果不開啟就是head-nommu.o,開啟就是head.o head-y := arch/arm/kernel/head$(MMUEXT).o \arch/arm/kernel/init_task.o
    • 1
    • 2
    • 3
    • 4
    • 1
    • 2
    • 3
    • 4
    • init-y
    #./Makefile #一開始init-y是個目錄 init-y := init/ #后續(xù)把init-y變量中所有符合%/的替換為%/built-in.o,這句之后init-y 被賦值為 init/built-in.o init-y := $(patsubst %/, %/built-in.o, $(init-y))
    • 1
    • 2
    • 3
    • 4
    • 5
    • 1
    • 2
    • 3
    • 4
    • 5

    所以最終vmlinux-init 實際上是:?
    1. arch/arm/kernel/head.o(這是Image/vmlinux的入口代碼)。?
    2. arch/arm/kernel/init_task.o?
    3. init/built-in.o?
    三者鏈接而來的。

    目標 vmlinux-main

    vmlinux-main := $(core-y) $(libs-y) $(drivers-y) $(net-y)
    • 1
    • 1
    • core-y
    #./Makefile core-y := usr/ ifeq ($(KBUILD_EXTMOD),) core-y += kernel/ mm/ fs/ ipc/ security/ crypto/ block/ #如果是編譯內(nèi)核的話,core-y最終包含: usr/ kernel/ mm/ fs/ ipc/ security/ crypto/ block/ #目錄下的built-in.o。編譯模塊的話,就只包含usr/build-in.o。 core-y := $(patsubst %/, %/built-in.o, $(core-y))
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    #./arch/arm/Makefile #除此之外,core-y還包含體系結(jié)構(gòu)相關(guān)的:arch/arm/kernel、mm、common #以及具體芯片相關(guān)的:mach-xxx,plat-xxx目錄下built-in.o文件(如mach-goldfish)。 #(見前面的include $(srctree)/arch/$(SRCARCH)/Makefile),幾乎涵蓋了所有built-in.o。 machdirs := $(patsubst %,arch/arm/mach-%/,$(machine-y)) platdirs := $(patsubst %,arch/arm/plat-%/,$(plat-y)) core-y += arch/arm/kernel/ arch/arm/mm/ arch/arm/common/ core-y += arch/arm/net/ core-y += $(machdirs) $(platdirs)
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • libs-y
    #libs-y也是包含具體體系結(jié)構(gòu)相關(guān)的庫,并且包括lib.a和built-in.o兩個文件 #./Makefile libs-y := lib/ #把$(libs-y)中所有的%/替換為%/lib.a -> libs-y1 libs-y1 := $(patsubst %/, %/lib.a, $(libs-y)) #把$(libs-y)中所有的%/替換為%/built-in.o -> libs-y2 libs-y2 := $(patsubst %/, %/built-in.o, $(libs-y)) ##libs-y等于二者的合并 libs-y := $(libs-y1) $(libs-y2)
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    #./arch/arm/Makefile #在libs-y的目錄基礎(chǔ)上加上arch/arm/lib/這個目錄,這是在libs-y1,libs-y2合并前加入的 libs-y := arch/arm/lib/ $(libs-y)
    • 1
    • 2
    • 3
    • 1
    • 2
    • 3
    • drivers-y
    #./Makefile drivers-y := drivers/ sound/ firmware/ #drivers, sound, firmware目錄的所有built-in.o文件 drivers-y := $(patsubst %/, %/built-in.o, $(drivers-y))
    • 1
    • 2
    • 3
    • 4
    • 1
    • 2
    • 3
    • 4
    #./arch/arm/Makefile #根據(jù)配置文件決定是否加入體系結(jié)構(gòu)相關(guān)的驅(qū)動 drivers-$(CONFIG_OPROFILE) += arch/arm/oprofile/
    • 1
    • 2
    • 3
    • 1
    • 2
    • 3
    • net-y
    #./Makefile net-y := net/ #net目錄的built-in.o net-y := $(patsubst %/, %/built-in.o, $(net-y))
    • 1
    • 2
    • 3
    • 4
    • 1
    • 2
    • 3
    • 4

    總結(jié)一下,vmlinux-main是由以下四個目標組成的:

    • core-y:?
    • 包含體系結(jié)構(gòu)無關(guān)的usr/ kernel/ mm/ fs/ ipc/ security/ crypto/ block/ 目錄下的built-in.o文件(如果是編譯module,則只包含usr/built-in.o)。
    • 包含體系結(jié)構(gòu)相關(guān)的文件,在arm下為arch/arm/kernel/ arch/arm/mm/ arch/arm/common/ arch/arm/net/下的built-in.o。
    • 包含具體芯片相關(guān)的文件,如arch/arm/plat-%/ arch/arm/mach-%/下的built-in.o。
    • libs-y: 包含arch/arm/lib/和 lib/目錄下的built-in.o和lib.a文件。
    • drivers-y: 包含drivers/ sound/ firmware/以及arch/arm/oprofile/(可選)目錄下的built-in.o文件。
    • net-y: 包含net/built-in.o文件。

    vmlinux的生成過程規(guī)則: rule_vmlinux__

    define rule_vmlinux__:#makefile -n的時候只是打印命令不會執(zhí)行,這個+號表示始終執(zhí)行#這貨生成.version文件舊的.version存到.old_version,內(nèi)容為"1"$(if $(CONFIG_KALLSYMS),,+$(call cmd,vmlinux_version))#調(diào)用cmd_vmlinux__命令,這個命令實際上就是將vmlinux的一堆依賴目標,連接為vmlinux$(call cmd,vmlinux__)#如果當(dāng)前$@為DIR/vmlinux,則這個命令被存儲到DIR/.vmlinux.cmd中#@D為$@中的目錄(DIR),@F為$@中的文件(vmlinux)$(Q)echo 'cmd_$@ := $(cmd_vmlinux__)' > $(@D)/.$(@F).cmd#quiet默認為空(有可能為silent_),為空時調(diào)用cmd_sysmap#cmd_sysmap = $(CONFIG_SHELL) $(srctree)/scripts/mksysmap#這里調(diào)用mksysmap來生成System.map,mksysmap就是個腳本,其內(nèi)容為:#$NM -n $1 | grep -v '\( [aNUw] \)\|\(__crc_\)\|\( \$[adt]\)' > $2$(Q)$(if $($(quiet)cmd_sysmap), \##顯示命令echo ' $($(quiet)cmd_sysmap) System.map' &&) \$(cmd_sysmap) $@ System.map; \if [ $$? -ne 0 ]; then \rm -f $@; \/bin/false; \fi;#應(yīng)該是再弄一遍符號表出來,比較符號是否正確$(verify_kallsyms) endefdefine verify_kallsyms$(Q)$(if $($(quiet)cmd_sysmap), \echo ' $($(quiet)cmd_sysmap) .tmp_System.map' &&) \$(cmd_sysmap) .tmp_vmlinux$(last_kallsyms) .tmp_System.map$(Q)cmp -s System.map .tmp_System.map || \(echo Inconsistent kallsyms data; \echo This is a bug - please report about it; \echo Try "make KALLSYMS_EXTRA_PASS=1" as a workaround; \rm .tmp_kallsyms* ; /bin/false ) endef
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10
    • 11
    • 12
    • 13
    • 14
    • 15
    • 16
    • 17
    • 18
    • 19
    • 20
    • 21
    • 22
    • 23
    • 24
    • 25
    • 26
    • 27
    • 28
    • 29
    • 30
    • 31
    • 32
    • 33
    • 34
    • 35
    • 36
    • 37
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10
    • 11
    • 12
    • 13
    • 14
    • 15
    • 16
    • 17
    • 18
    • 19
    • 20
    • 21
    • 22
    • 23
    • 24
    • 25
    • 26
    • 27
    • 28
    • 29
    • 30
    • 31
    • 32
    • 33
    • 34
    • 35
    • 36
    • 37

    rule_vmlinux__ -> cmd_vmlinux__

    #?=是 如果沒有被復(fù)制,則等于,這里是調(diào)用LD連接vmlinux所需的各種文件#LDFLAGS,LDFLAGS_vmlinux這些變量會作為LD的鏈接參數(shù)#-o $@指定最終生成的文件為vmlinuxcmd_vmlinux__ ?= $(LD) $(LDFLAGS) $(LDFLAGS_vmlinux) -o $@ \# -T指定鏈接腳本文件為vmlinux-lds 后面跟著的$(vmlinux-init)為一堆目標文件-T $(vmlinux-lds) $(vmlinux-init) \##如果ld載入了一個庫,發(fā)現(xiàn)該庫中,有UNDF,未被定義的變量,有了這個參數(shù)的指示后,就會在這一堆.a和.o文件里面反復(fù)搜索,直至找到為止,否則,如果在已經(jīng)加載的庫中,找不到,就會報錯????--start-group $(vmlinux-main) --end-group \##從$^中去除$(vmlinux-lds) $(vmlinux-init) $(vmlinux-main) vmlinux.o FORCE中的字符,并返回結(jié)果,這里的結(jié)果就是.tmp_kallsyms2.o(沒用kallsyms.o)$(filter-out $(vmlinux-lds) $(vmlinux-init) $(vmlinux-main) vmlinux.o FORCE ,$^)
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10

    rule_vmlinux生成的vmlinux.cmd:

    #在mt6582下,vmlinux.cmd如下:cmd_vmlinux := arm-linux-androideabi-ld.bfd \ #$(LD)-EL -p --no-undefined -X --emit-relocs --build-id \ #$LDFLAGS) $(LDFLAGS_vmlinux)-o vmlinux \ #$-o $@-T arch/arm/kernel/vmlinux.lds \ #-T $(vmlinux-lds)arch/arm/kernel/head.o arch/arm/kernel/init_task.o init/built-in.o \ #$(vmlinux-init)--start-group \usr/built-in.o arch/arm/vfp/built-in.o arch/arm/kernel/built-in.o arch/arm/mm/built-in.o arch/arm/common/built-in.o arch/arm/net/built-in.o mediatek/platform/mt6582/kernel/core/built-in.o kernel/built-in.o mm/built-in.o fs/built-in.o ipc/built-in.o security/built-in.o crypto/built-in.o block/built-in.o arch/arm/lib/lib.a lib/lib.a arch/arm/lib/built-in.o lib/built-in.o drivers/built-in.o sound/built-in.o firmware/built-in.o mediatek/kernel/built-in.o mediatek/custom/out/kernel/built-in.o mediatek/platform/mt6582/kernel/drivers/built-in.o aliyun/security/built-in.o net/built-in.o \ #$(vmlinux-main)--end-group \.tmp_kallsyms2.o #$(filter-out $(vmlinux-lds) $(vmlinux-init) $(vmlinux-main) vmlinux.o FORCE ,$^)
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10
    • 11
    • 12
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10
    • 11
    • 12

    也就是說vmlinux實際上是由vmlinux.lds 連接vmlinux-init, vmlinux-main和.tmp_kallsyms2.o而成的,與vmlinx.o沒有鏈接的關(guān)系!!!

    vmlinux.o的生成

    #vmlinux.o只依賴于$(modpost-init) $(vmlinux-main)兩個目標文件, ##其最終調(diào)用的是rule_vmlinux-modpost vmlinux.o: $(modpost-init) $(vmlinux-main) FORCE$(call if_changed_rule,vmlinux-modpost)define rule_vmlinux-modpost:#調(diào)用cmd_vmlinux-modpost,這個函數(shù)是用來鏈接生成vmlinux.o的+$(call cmd,vmlinux-modpost)#實際上調(diào)用的是make -f $(srctree)/scripts/Makefile.modpost vmlinux.o$(Q)$(MAKE) -f $(srctree)/scripts/Makefile.modpost $@#dot-target是在$@的前面加個.,這里就是.vmlinux.o.cmd,這里是#將命令存儲到.vmlinux.o.cmd$(Q)echo 'cmd_$@ := $(cmd_vmlinux-modpost)' > $(dot-target).cmd endif#cmd_vmlinux-modpost負責(zé)生成vmlinux.o,其規(guī)則和vmlinux的規(guī)則差不多#其差別主要在于,vmlinux.o沒有指定--no-undefined編譯選項#沒有指定鏈接腳本,沒有指定符號表cmd_vmlinux-modpost = $(LD) $(LDFLAGS) -r -o $@ \$(vmlinux-init) --start-group $(vmlinux-main) --end-group \$(filter-out $(vmlinux-init) $(vmlinux-main) FORCE ,$^)
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10
    • 11
    • 12
    • 13
    • 14
    • 15
    • 16
    • 17
    • 18
    • 19
    • 20
    • 21
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10
    • 11
    • 12
    • 13
    • 14
    • 15
    • 16
    • 17
    • 18
    • 19
    • 20
    • 21

    vmlinux.o的生成命令(.vmlinux.o.cmd)

    cmd_vmlinux.o := arm-linux-androideabi-ld.bfd \ #$(LD)-EL \#$(LDFLAGS)-r -o vmlinux.o \# -r -o $@ ,-r指定了可重定位的輸出文件arch/arm/kernel/head.o arch/arm/kernel/init_task.o init/built-in.o \#$(vmlinux-init)--start-group \usr/built-in.o arch/arm/vfp/built-in.o arch/arm/kernel/built-in.o arch/arm/mm/built-in.o arch/arm/common/built-in.o arch/arm/net/built-in.o mediatek/platform/mt6582/kernel/core/built-in.o kernel/built-in.o mm/built-in.o fs/built-in.o ipc/built-in.o security/built-in.o crypto/built-in.o block/built-in.o arch/arm/lib/lib.a lib/lib.a arch/arm/lib/built-in.o lib/built-in.o drivers/built-in.o sound/built-in.o firmware/built-in.o mediatek/kernel/built-in.o mediatek/custom/out/kernel/built-in.o mediatek/platform/mt6582/kernel/drivers/built-in.o aliyun/security/built-in.o net/built-in.o \#$(vmlinux-main)--end-group#\$(filter-out $(vmlinux-init) $(vmlinux-main) FORCE ,$^)為空
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9

    make -f $(srctree)/scripts/Makefile.modpost vmlinux.o

    rule_vmlinux-modpost生成vmlinux.o后會調(diào)用

    $(Q)$(MAKE) -f $(srctree)/scripts/Makefile.modpost $@,解析后就是
    • 1
    • 1

    解析后就是:

    make -f $(srctree)/scripts/Makefile.modpost vmlinux.o
    • 1
    • 1
    #./$(srctree)/scripts/Makefile.modpost modpost = scripts/mod/modpost \$(if $(CONFIG_MODVERSIONS),-m) \$(if $(CONFIG_MODULE_SRCVERSION_ALL),-a,) \$(if $(KBUILD_EXTMOD),-i,-o) $(kernelsymfile) \$(if $(KBUILD_EXTMOD),-I $(modulesymfile)) \$(if $(KBUILD_EXTRA_SYMBOLS), $(patsubst %, -e %,$(KBUILD_EXTRA_SYMBOLS))) \$(if $(KBUILD_EXTMOD),-o $(modulesymfile)) \$(if $(CONFIG_DEBUG_SECTION_MISMATCH),,-S) \$(if $(KBUILD_EXTMOD)$(KBUILD_MODPOST_WARN),-w) \$(if $(cross_build),-c) #根據(jù)make -f的指定,生成vmlinux.o目標 vmlinux.o: FORCE$(call cmd,kernel-mod) #最終調(diào)用的命令如:scripts/mod/modpost -o $(srctree)/Module.symvers -S vmlinux.o #實際上這一句makefile是用來生成Module.symvers文件的,這個文件是對內(nèi)核函數(shù)做crc簽名校驗的 cmd_kernel-mod = $(modpost) $@
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10
    • 11
    • 12
    • 13
    • 14
    • 15
    • 16
    • 17
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10
    • 11
    • 12
    • 13
    • 14
    • 15
    • 16
    • 17

    Module.symvers文件只有在開啟CONFIG_MODVERSIONS才生效的,否則里面的crc全是0,我這里沒有開,內(nèi)容如下:

    <CRC> <Symbol> <module> <type> 0x00000000 cfg80211_send_rx_assoc vmlinux EXPORT_SYMBOL 0x00000000 generic_file_splice_write vmlinux EXPORT_SYMBOL 0x00000000 set_anon_super vmlinux EXPORT_SYMBOL 0x00000000 kmem_cache_alloc vmlinux EXPORT_SYMBOL 0x00000000 replace_page_cache_page vmlinux EXPORT_SYMBOL_GPL 0x00000000 __cond_resched_softirq vmlinux EXPORT_SYMBOL 0x00000000 mt_fh_popod_restore vmlinux EXPORT_SYMBOL 0x00000000 i2c_put_adapter vmlinux EXPORT_SYMBOL 0x00000000 rtc_class_open vmlinux EXPORT_SYMBOL_GPL 0x00000000 scsi_sense_key_string vmlinux EXPORT_SYMBOL ......
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10
    • 11
    • 12
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10
    • 11
    • 12

    總結(jié)一下:

    • vmlinux依賴于目標文件vmlinux.o,但是二者的生成沒有直接關(guān)系,即vmlinux并不鏈接vmlinux.o文件
    • vmlinux和vmlinux.o的區(qū)別主要在于:?
    • vmlinux指定了–no-undefined編譯選項,不可以有未決符號,而vmlinux.o可以有。
    • vmlinux指定了鏈接腳本vmlinux.lds,vmlinux.o沒有連接腳本。
    • vmlinux連接了符號表*kallsyms*.o文件,vmlinux.o沒有連接符號表。
    • vmlinux沒指定-r選項,vmlinux.o指定了-r選項,-r是用來生成可重定位的目標文件用的,這個選項導(dǎo)致了vmlinux.o雖然鏈接的較vmlinux少,但實際體積比vmlinux要大(在我編譯出的鏡像中,vmlinux大小61MB,包含56個段; vmlinx.o大小109MB,包含12119個段,其中有6061個段為重定位段,另外有5981個段為各種ksy*段,如__ksymtab_strings。

    zImage的生成

    #./arch/arm/Makefile #在根目錄makefile中的include $(srctree)/arch/$(SRCARCH)/Makefile會include當(dāng)前文件 #這是all出現(xiàn)的第二個目標,all的所有目標會合并,合并后就是vmlinux和zImage all: $(KBUILD_IMAGE) KBUILD_IMAGE := zImage #zImage還依賴于vmlinux zImage Image xipImage bootpImage uImage: vmlinux#此命令解析后類似: #make -f scripts/Makefile.build obj=arch/arm/boot MACHINE = XXX arch/arm/boot/zImage#調(diào)用makefile.build作為makefile的腳本,obj和MACHINE都為變量#要build的目標為arch/arm/boot/zImage,這個就是target$(Q)$(MAKE) $(build)=$(boot) MACHINE=$(MACHINE) $(boot)/$@
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10
    • 11
    • 12
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10
    • 11
    • 12
    #./scripts/makefile.build #初始化各個變量為空 obj-y := obj-m := lib-y := lib-m := ##包含配置文件,沒有就算了(這里沒有) -include include/config/auto.conf ##導(dǎo)入內(nèi)部函數(shù) include scripts/Kbuild.include src := $(obj) ##這一句是在src目錄下找Makefile文件,對于arch/arm/boot來說,最終找到的是 ##arch/arm/boot/Makefile kbuild-dir := $(if $(filter /%,$(src)),$(src),$(srctree)/$(src)) kbuild-file := $(if $(wildcard $(kbuild-dir)/Kbuild),$(kbuild-dir)/Kbuild,$(kbuild-dir)/Makefile) ##所以對于arch/arm/boot來說,最終這里include了./arch/arm/boot/Makefile ##最終要編譯的目標arch/arm/boot/zImage就是在./arch/arm/boot/Makefile中定義的 include $(kbuild-file)
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10
    • 11
    • 12
    • 13
    • 14
    • 15
    • 16
    • 17
    • 18
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10
    • 11
    • 12
    • 13
    • 14
    • 15
    • 16
    • 17
    • 18
    #./arch/arm/boot/Makefile ifneq ($(MACHINE),) #這里一般記錄 zreladdr-y,params_phys-y,initrd_phys-y 等信息 include $(srctree)/$(MACHINE)/Makefile.boot endif ZRELADDR := $(zreladdr-y) PARAMS_PHYS := $(params_phys-y) INITRD_PHYS := $(initrd_phys-y) #這個文件是被include進來的,$(obj)這里就是arch/arm/boot #這個$(obj)/zImage展開的話就是arch/arm/boot/zImage $(obj)/zImage: $(obj)/compressed/vmlinux FORCE##這里是向if_changed傳入了objcopy,if_changed會給其加上cmd_開頭的頭,如果這里得到執(zhí)行##最終執(zhí)行的會是cmd_objcopy$(call if_changed,objcopy)@echo ' Kernel: $@ is ready'
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10
    • 11
    • 12
    • 13
    • 14
    • 15
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10
    • 11
    • 12
    • 13
    • 14
    • 15
    #./scripts/makefile.lib cmd_objcopy = $(OBJCOPY) $(OBJCOPYFLAGS) $(OBJCOPYFLAGS_$(@F)) $< $@
    • 1
    • 2
    • 1
    • 2

    所以zImage實際上是依賴于$(obj)/compressed/vmlinux的,是后者執(zhí)行了一個objcopy -binary過來的($(obj)/compressed/vmlinux并不是vmlinux,前者是內(nèi)核Image壓縮為piggy.gz后再次生成的一個壓縮后的elf鏡像,而后者是內(nèi)核的鏡像,$(obj)/compressed/vmlinux大小約為2.XMB,后面也稱其為vmlinux(小),而另一個稱為vmlinux(大))其命令行如下:

    cmd_arch/arm/boot/zImage := arm-linux-androideabi-objcopy -O binary -R .comment -S arch/arm/boot/compressed/vmlinux arch/arm/boot/zImage
    • 1
    • 1

    目標?$(obj)/compressed/vmlinux

    #./arch/arm/boot/Makefile #vmlinux(小)依賴于Image $(obj)/compressed/vmlinux: $(obj)/Image FORCE#這句和前面類似,還是make -f makefile.build #最終include arch/arm/boot/compressed/makefile#目標$(obj)/compressed/vmlinux定義在arch/arm/boot/compressed/makefile中$(Q)$(MAKE) $(build)=$(obj)/compressed $@ #Image又依賴于vmlinux(大) $(obj)/Image: vmlinux FORCE#Image同樣是vmlinux(大)通過objcopy -binary過來的,.Image.cmd如下:#cmd_arch/arm/boot/Image := arm-linux-androideabi-objcopy \#-O binary -R .comment -S vmlinux arch/arm/boot/Image$(call if_changed,objcopy)@echo ' Kernel: $@ is ready'
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10
    • 11
    • 12
    • 13
    • 14
    • 15
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10
    • 11
    • 12
    • 13
    • 14
    • 15
    #./arch/arm/boot/compress/Makefile HEAD = head.o OBJS = #這個OBJS根據(jù)不同CONFIG還可能有多個.o OBJS += string.o lib1funcs = $(obj)/lib1funcs.o ashldi3 = $(obj)/ashldi3.o#這里是piggy.gzip,這個文件實際上就是壓縮了Image,再加上piggy.S編譯來的 #這里的suffix_y最終執(zhí)行的是cmd_gzip(./script/makefile.lib) $(obj)/piggy.$(suffix_y): $(obj)/../Image FORCE$(call if_changed,$(suffix_y))#piggy.gzip.o依賴于piggy.gzip,這只是依賴關(guān)系,默認沒有編譯腳本,所以 #默認編譯的是piggy.gzip.S $(obj)/piggy.$(suffix_y).o: $(obj)/piggy.$(suffix_y) FORCE#vmlinux(小)也是有個自己的鏈接腳本vmlinux.lds的,這個和vmlinux(大)的是不同的兩個腳本。 $(obj)/vmlinux: $(obj)/vmlinux.lds $(obj)/$(HEAD) $(obj)/piggy.$(suffix_y).o \$(addprefix $(obj)/, $(OBJS)) $(lib1funcs) $(ashldi3) FORCE@$(check_for_multiple_zreladdr)$(call if_changed,ld)@$(check_for_bad_syms)
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10
    • 11
    • 12
    • 13
    • 14
    • 15
    • 16
    • 17
    • 18
    • 19
    • 20
    • 21
    • 22
    • 23
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10
    • 11
    • 12
    • 13
    • 14
    • 15
    • 16
    • 17
    • 18
    • 19
    • 20
    • 21
    • 22
    • 23

    文件piggy.gzip.s

    #此文件直接將piggy.zip包含進來了.section .piggydata,#alloc.globl input_data input_data:.incbin "arch/arm/boot/compressed/piggy.gzip".globl input_data_end input_data_end:
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7

    zImage的生成流程圖

    從vmlinux到zImage的步驟如圖:?

    *.cmd

    • 在構(gòu)建內(nèi)核時,各個*.o的目錄下都有一個.*.cmd,這個文件是記錄這個.o最終執(zhí)行的編譯命令的,如vmlinux.cmd和.vmlinux.o.cmd,從vmlinux到zImage的步驟總結(jié)如下:
    //1.vmlinux(61MB)->Image(5.1M) //./arch/arm/boot/.Image.cmd cmd_arch/arm/boot/Image := arm-eabi-objcopy \-O binary -R .comment -S vmlinux arch/arm/boot/Image //2. Image(5.1MB)->piggy.gzip(1.7MB)(gzip -9 壓縮) //./arch/arm/boot/compressed/.piggy.gz.cmd cmd_arch/arm/boot/compressed/piggy.gz := gzip -f -9 \< arch/arm/boot/compressed/../Image > \arch/arm/boot/compressed/piggy.gz //3. piggy.gzip(1.7MB)->piggy.o(1.7MB) //實際上是將piggy.gz通過piggy.S編譯進piggy.o文件中,piggy.S文件僅有6行 //./arch/arm/boot/compressed/.piggy.o.cmd//4. head.o 、piggy.o 、misc.o,piggy.o -> vmlinux(2.6MB) //這個vmlinux是在./arch/arm/boot/compressed目錄下的,且經(jīng)過壓縮且含有自解壓代碼的內(nèi)核。 //./arch/arm/boot/compressed/.vmlinux.cmd cmd_arch/arm/boot/compressed/vmlinux := arm-eabi-ld -EL\--defsym _kernel_bss_size=1419856 \--defsym zreladdr=0x00008000 \-p --no-undefined -X -T \arch/arm/boot/compressed/vmlinux.lds \arch/arm/boot/compressed/head.o \arch/arm/boot/compressed/piggy.gzip.o \arch/arm/boot/compressed/misc.o \arch/arm/boot/compressed/decompress.o \arch/arm/boot/compressed/string.o \arch/arm/boot/compressed/lib1funcs.o \arch/arm/boot/compressed/ashldi3.o \-o arch/arm/boot/compressed/vmlinux//5. vmlinux(2.6MB)->zImage(2.5MB) //將arch/arm/boot/compressed/vmlinux去除調(diào)試信息、注釋、符號表等內(nèi)容,生成arch/arm/boot/zImage,這是一個可以使用的linux內(nèi)核映像文件了,一個linux內(nèi)核鏡像,最終約2.5MB大小 //./arch/arm/boot/.zImage.cmd cmd_arch/arm/boot/zImage := arm-eabi-objcopy \-O binary -R .comment \-S arch/arm/boot/compressed/vmlinux \arch/arm/boot/zImage
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10
    • 11
    • 12
    • 13
    • 14
    • 15
    • 16
    • 17
    • 18
    • 19
    • 20
    • 21
    • 22
    • 23
    • 24
    • 25
    • 26
    • 27
    • 28
    • 29
    • 30
    • 31
    • 32
    • 33
    • 34
    • 35
    • 36
    • 37
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10
    • 11
    • 12
    • 13
    • 14
    • 15
    • 16
    • 17
    • 18
    • 19
    • 20
    • 21
    • 22
    • 23
    • 24
    • 25
    • 26
    • 27
    • 28
    • 29
    • 30
    • 31
    • 32
    • 33
    • 34
    • 35
    • 36
    • 37

    vmlinux.ld

    //vmlinux.lds.s用于對ld的輸出進行排版//指定一個特定的輸出機器架構(gòu),可以使用arm-XXX-objdump -f來查看一個文件的機器架構(gòu) OUTPUT_ARCH(arm) //ENTRY用來設(shè)置程序的入口點 ENTRY(_start) SECTIONS { //這個.代表默認的地址計數(shù)器,如果一個段沒指定地址,就用當(dāng)前地址計數(shù) //器的默認地址,這個地址在每次應(yīng)用于一個段之后,會自加。. = 0;_text = .;.text : {//_start是程序入口地址,被放在了0x00000000的位置,從此可以反向推出,此芯片的上電啟動地址為0x0000000,這個vmlinux.lds用于//生成那個2.6MB的vmlinux,所以這個0x00000000也是最終鏡像zImage的啟動地址。_start = .;*(.start)*(.text)*(.text.*)*(.fixup)*(.gnu.warning)*(.glue_7t)*(.glue_7)}.rodata : {*(.rodata)*(.rodata.*)}.piggydata : {*(.piggydata)}. = ALIGN(4);_etext = .;.got.plt : { *(.got.plt) }_got_start = .;.got : { *(.got) }_got_end = .;.pad : { BYTE(0); . = ALIGN(8); }_edata = .;. = ALIGN(8);__bss_start = .;.bss : { *(.bss) }_end = .;. = ALIGN(8); .stack : { *(.stack) }.stab 0 : { *(.stab) }.stabstr 0 : { *(.stabstr) }.stab.excl 0 : { *(.stab.excl) }.stab.exclstr 0 : { *(.stab.exclstr) }.stab.index 0 : { *(.stab.index) }.stab.indexstr 0 : { *(.stab.indexstr) }.comment 0 : { *(.comment) } }
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10
    • 11
    • 12
    • 13
    • 14
    • 15
    • 16
    • 17
    • 18
    • 19
    • 20
    • 21
    • 22
    • 23
    • 24
    • 25
    • 26
    • 27
    • 28
    • 29
    • 30
    • 31
    • 32
    • 33
    • 34
    • 35
    • 36
    • 37
    • 38
    • 39
    • 40
    • 41
    • 42
    • 43
    • 44
    • 45
    • 46
    • 47
    • 48
    • 49
    • 50
    • 51
    • 52
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10
    • 11
    • 12
    • 13
    • 14
    • 15
    • 16
    • 17
    • 18
    • 19
    • 20
    • 21
    • 22
    • 23
    • 24
    • 25
    • 26
    • 27
    • 28
    • 29
    • 30
    • 31
    • 32
    • 33
    • 34
    • 35
    • 36
    • 37
    • 38
    • 39
    • 40
    • 41
    • 42
    • 43
    • 44
    • 45
    • 46
    • 47
    • 48
    • 49
    • 50
    • 51
    • 52

    參考資料

    [1].http://lli_njupt.0fees.net/ar01s07.html?ckattempt=1?
    [2].http://cache.baiducontent.com/c?m=9d78d513d99d17b8589c837e7b01d6160e54f6743da791532c94d55f92144c413171e2cb72624d4391d27d1716df4e4b9bf62173471456b28cbc8d5dabba85592e9c60742e13dc0754910eaeb85b388465d54de9d848a7e1a461cfb9d2a48e090cd705523cd3abd50d5603cd1ba34862bdedd813544817ceb06472f82d3173c83447c218aab9657900f5b18d0111853dd71545ccf366ee2915c142f940597f1af75bb67c027a66f74853a11f615d85ec29a1702e5724c213ecfb9fe1b41fd09ab977c3a797b828e122a698bbae30036d&p=c46cce10ba904ead08e2977c0908cd&newp=8570c54ad5c145c30be296645b5f88231610db2151d4d31013&user=baidu&fm=sc&query=ld++%2D%2Dstart%2Dgroup%B5%C4%D7%F7%D3%C3&qid=89430f6200031c87&p1=7

    總結(jié)

    以上是生活随笔為你收集整理的arm-linux内核编译过程小结的全部內(nèi)容,希望文章能夠幫你解決所遇到的問題。

    如果覺得生活随笔網(wǎng)站內(nèi)容還不錯,歡迎將生活随笔推薦給好友。