Tiny4412 Linux 內核配置流程


1.配置交叉編譯器

默認情況下,內核構建的是與宿主機相同的體系架構鏡像。如果要交叉編譯,需要設置兩個變量ARCH和CORSS_COMPILE。

①ARCH:指明目標體系架構,如x86、arm、mips等。

②CROSS_COMPILE:指定使用的交叉編譯器的前綴。例如arm-linux-。在內核頂層的Makefile中,可以看到工具鏈中的編譯器、鏈接器等都是以$(CROSS_COMPILE)作為前綴。

AS              = $(CROSS_COMPILE)as  
LD              = $(CROSS_COMPILE)ld
REAL_CC         = $(CROSS_COMPILE)gcc
CPP             = $(CC) -E
AR              = $(CROSS_COMPILE)ar
NM              = $(CROSS_COMPILE)nm
STRIP           = $(CROSS_COMPILE)strip
OBJCOPY         = $(CROSS_COMPILE)objcopy
OBJDUMP         = $(CROSS_COMPILE)objdump

我們可以在每次執行make時,通過下面的命令來給這兩個變量賦值

make ARCH=arm CROSS_COMPILE=arm-linux-

或者直接修改頂層Makefile,將

ARCH                                        ?=  $  (SUBARCH)
CROSS_COMPILE                               ?=

修改為

ARCH                                        ?=  arm
CROSS_COMPILE                               ?= arn-linux-

2.加載默認配置

在內核源碼 arch/<arch>/configs 目錄下,內核提供了各種平台的默認配置文件,加載默認配置時,我們可以使用

make ARCH=arm CROSS_COMPILE=arm-linux- xxx_defconfig

這個操作等同於將arch/arm/configs/目錄下的xxx_defconfig文件復制為.config

我們可以使用命令

make help

來獲取幫助

3.配置內核

我們可使用命令

make menuconfig

來以菜單的形式配置內核。

4.生成內核

我們可以通過下面命令編譯內核

make zImage

可以通過下面的命令編譯內核模塊

make modules

編譯生成的內核鏡像位於內核源碼/arch/arm/boot目錄和arch/arm/boot/compressed目錄下。

①vmlinux.o是鏈接后生成的內核的目標文件

②vmlinux(根目錄)是ELF格式的內核

③System.map是內核的富豪榜

④Image是二進制的內核文件,由vmlinux轉換而成

⑤vmlinux(compressed目錄)是經壓縮的vmlinux鏡像(通過gzip算法壓縮)和解壓縮程序的組合體,也是ELF格式

⑥zImage是解壓縮程序和內核的組合

5.內核構建系統

名稱 描述
頂層Makefile 他是所有Makefile文件的核心,從總體上控制內核的編譯和鏈接
.config 配置文件,在配置內核時產生。所有Makefile文件(包括頂層目錄及各級子目錄)都是根據.config來決定使用哪些文件
arch/$(ARCH)/Makefile 對應體系結構的Makefile,它用來決定哪些體系結構相關的文件參與內核的生成,並提供一些規則來生成特定格式的內核映像。
scripts/makefile.* Makefile公用的通用規則、腳本等
kbuild Makefiles 各級子目錄下的Makefile,他們相對簡單,被上一層Makefile調用來編譯當前目錄下的文件

Makefile:分布在內核源代碼中的Makefile,定義內核的編譯規則,配合Kconfig使用

Kconfig:配置文件,給用戶提供配置選項的功能,make menuconfig 等命令根據此文件生成配置菜單

配置工具:包括配置命令解析器(解析Kconfig)和內核配置用戶界面程序等

5.1 內核Kconfig

在執行make zImage來構建內核鏡像之前,我們通常會響拷貝一個默認的xxx_defconfig來替換掉.config,或者運行 make xxx_defconfig以此來獲得一個默認的內核配置文件,然后再運行make menuconfig 等來進一步定制內核。

make menuconfig等配置工具是通過讀取arch/<arch>/Kconnfig 文件來生成配置界面的,這個文件是所有配置文件的總入口,它會包含其他目錄的Kconfig文件。

內核源碼每個子目錄中,都有一個Makefile文件和Kconfig文件。Makefile用來配置目標文件的生成過程。Kconfig用於配置內核,它就是各種配置界面的源文件。內核的配置工具讀取各個Kconfig文件,生成配置界面供開發人員配置內核最后生成配置文件.config。

內核的配置界面以樹狀的菜單形式組織,主菜單下有若干子菜單,子菜單下又有子菜單或配置選項。每個子菜單或選項都有依賴關系,這些依賴關系用來確定它們是否顯示。只有被依賴的父項已經被選中,子項才會顯示。下面看一下Kconfig的基本語法。

Kconfig語法比較豐富,按功能可分為配置選項描述語句和菜單結構描述語句。

①Kconfig 文件的基本要素:config關鍵字(entry)

config 條目常被其他條目包含,用來生成菜單,進行多項選擇等。config 條目用來配置一個選項,或者這么說,它用於生成一個變量,這個變量會連同它的值一起被寫入配置文件 .config 中。也就是說config關鍵字定義了新的配置選項,之后的幾行定義了該配置選項的屬性。配置選項的屬性包括類型、數據范圍、輸入提示、依賴關系、幫助信息和默認值等。

比如有一個config 條目用來配置CONFIG_XXX,根據用戶的選擇,.config文件中可能出現下面3種配置結果中的一個。

CONFIG_XXX=y   # 對應的文件被編進內核
CONFIG_XXX=m   # 對應的文件被編成模塊
#CONFIG_XXX   # 對應的文件沒有被使用

比如

config TINY4412_LEDS #配置選項的名稱
        tristate "LED Support for FriendlyARM Tiny4412 GPIO LEDs"
       #tristate是變量類型有5種
       #Bool  布爾類型,結果是Y[*] ,  N[]
       #tristate 三項選擇,結果是Y[*], N[], M[m]
       #String  字符串, 結果(arm-linux-)
       #Hex   十六進制
       #Int   十進制
        depends on MACH_TINY4412 #依賴
        #當依賴滿足事,當前配置選項的提示信息才會出現,才能設置當前配置選項
        #如果依賴條件不滿足,則它取默認值。
        default y #默認為y
        help #幫助信息
          This option enables support for LEDs connected to GPIO lines
          on Tiny4412 boards.

在通過make menuconfig來配置時的的效果如下

②menu關鍵字

menu條目用於生成菜單, 在menuconfig 中是以------>形式出現 格式如下:

“menu” <prompt>
<menu options>
<menu block>
"endmenu"

menu之后字符串是菜單名,“menu”和“endmunu”之間有很多config條目。在配置界面上回出現如下字樣的菜單,移動光標選中它后按回車鍵進入,就會看到這些config條目定義的配置選項。

③Source關鍵字

在當前Kconfig包含其它目錄下的kconfig,用於讀入另一個Kconfig文件,格式如下:

“source” <prompt>

下面看一個例子

menu "Device Drivers"  #菜單開始
source "drivers/tty/Kconfig" #引入drivers/tty目錄下的Kconfig
......
config TINY4412_LEDS
        tristate "LED Support for FriendlyARM Tiny4412 GPIO LEDs"
        depends on MACH_TINY4412
        default y
        help
          This option enables support for LEDs connected to GPIO lines
          on Tiny4412 boards.
......
endmenu#菜單結束

④Choice關鍵字

choice條目將多個類似的配置選項組合在一起,供用戶單選或多選,格式如下:

“choice”
<choice options>
<choice block>
"end choice"

實際使用中,也是在“choice”和“endchoice”之間定義多個config條目。

同樣也來看一個例子

choice
    prompt "Kernel compression mode"
    default KERNEL_GZIP
    depends on HAVE_KERNEL_GZIP || HAVE_KERNEL_BZIP2 || HAVE_KERNEL_LZMA || HAVE_KERNEL_XZ || HAVE_KERNEL_LZO
    help
      The linux kernel is a kind of self-extracting executable.
      Several compression algorithms are available, which differ
      in efficiency, compression and decompression speed.
      Compression speed is only relevant when building a kernel.
      Decompression speed is relevant at each boot.
      If you have any problems with bzip2 or lzma compressed
      kernels, mail me (Alain Knaff) <alain@knaff.lu>. (An older
      version of this functionality (bzip2 only), for 2.4, was
      supplied by Christian Ludwig)
      High compression options are mostly useful for users, who
      are low on disk space (embedded systems), but for whom ram
      size matters less.
      If in doubt, select 'gzip'
config KERNEL_GZIP
    bool "Gzip"
    depends on HAVE_KERNEL_GZIP
    help
      The old and tried gzip compression. It provides a good balance
      between compression ratio and decompression speed.
config KERNEL_BZIP2
    bool "Bzip2"
    depends on HAVE_KERNEL_BZIP2
    help
      Its compression ratio and speed is intermediate.
      Decompression speed is slowest among the choices.  The kernel
      size is about 10% smaller with bzip2, in comparison to gzip.
      Bzip2 uses a large amount of memory. For modern kernels you
      will need at least 8MB RAM or more for booting.
config KERNEL_LZMA
    bool "LZMA"
    depends on HAVE_KERNEL_LZMA
    help
      This compression algorithm's ratio is best.  Decompression speed
      is between gzip and bzip2.  Compression is slowest.
      The kernel size is about 33% smaller with LZMA in comparison to gzip.
config KERNEL_XZ
    bool "XZ"
    depends on HAVE_KERNEL_XZ
    help
      XZ uses the LZMA2 algorithm and instruction set specific
      BCJ filters which can improve compression ratio of executable
      code. The size of the kernel is about 30% smaller with XZ in
      comparison to gzip. On architectures for which there is a BCJ
      filter (i386, x86_64, ARM, IA-64, PowerPC, and SPARC), XZ
      will create a few percent smaller kernel than plain LZMA.
      The speed is about the same as with LZMA: The decompression
      speed of XZ is better than that of bzip2 but worse than gzip
      and LZO. Compression is slow.
config KERNEL_LZO
    bool "LZO"
    depends on HAVE_KERNEL_LZO
    help
      Its compression ratio is the poorest among the choices. The kernel
      size is about 10% bigger than gzip; however its speed
      (both compression and decompression) is the fastest.
endchoice

配置時的界面如下所示

5.2 內核中的Makefile

內核中的Makefile的作用主要有以下幾點:

 

①決定編譯哪些文件

②怎樣編譯這些文件

③怎樣連接這些文件,最重要的是它們的順序如何

(1)決定編譯哪些文件

Linux內核的編譯過程從頂層Makefile開始,然后遞歸地進入各級子目錄調用他們的makefile,分為3個步驟:

 

①頂層Makefile 決定內核根目錄下哪些子目錄將被編進內核;

②arch/<arch>/Makefile 決定arch/<arch>目錄下哪些文件、哪些目錄將被編進內核;

③各級子目錄下的Makefile決定所在目錄下哪些文件將被編進內核,哪些文件將被編成模塊(即驅動程序),進入哪些子目錄繼續調用它們的Makefile。

 

在頂層Makefile 中可以看到如下內容:

core-y          += kernel/ mm/ fs/ ipc/ security/ crypto/ block/
 # Objects we will link into vmlinux / subdirs we need to visit
init-y          := init/  
drivers-y       := drivers/ sound/ firmware/
net-y           := net/ 
libs-y          := lib/ 
core-y          := usr/ 

我們可以看到,最重要的arch目錄沒有出現在內核中。它在arch/$(ARCH)/Makefile中被包含進內核,在頂層Makefile中直接包含了這個Makefile

include $(srctree)/arch/$(SRCARCH)/Makefile

對於ARCH變量,可以在執行make時傳入,比如make ARCH=arm 。另外,對於非X86平台,還需要指定交叉編譯工具,這也可以在執行make 命令時傳入,比如make CROSS_COPILE=arm-linux- 。

對於arch/<arch>/Makefile,以ARM為例,在arch/arm/Makefile 中可以看到如下內容:

#對應arch/arm/kernel/head.o
head-y        := arch/arm/kernel/head$(MMUEXT).o 
......
core-$(CONFIG_FPE_NWFPE)    += arch/arm/nwfpe/
core-$(CONFIG_FPE_FASTFPE)    += $(FASTFPE_OBJ)
core-$(CONFIG_VFP)        += arch/arm/vfp/
# If we have a machine-specific directory, then include it in the build.
core-y                += arch/arm/kernel/ arch/arm/mm/ arch/arm/common/
core-y                += arch/arm/net/
core-y                += $(machdirs) $(platdirs)
drivers-$(CONFIG_OPROFILE)      += arch/arm/oprofile/
libs-y                := arch/arm/lib/ $(libs-y)

CONFIG_在配置內核時定義,它的值有3種:y、m或空。y表示編進內核,m表示編為模塊,空表示不使用。

編譯內核時,將依次進入init-y、core-y、libs-y、drivers-y和net-y 所列出的目錄中執行它們的Makefile,每個子目錄都會生成一個 built-in.o(libs-y所列目錄下,有可能生成lib.a文件)。最后,head-y所表示的文件將和在這些built-in.o、lib.a 一起被連接成內核映像文件 vmlinux。

在各級子目錄下的也有各自的Makefile它的主要作用和為:

在配置內核時,生成配置文件.config。內核頂層Makefile使用如下語句間接包含.config 文件,以后就根據.config中定義的各個變量決定編譯哪些文件。它包含了include/config/auto.conf 文件,然后將.config文件中的注釋去掉,並根據頂層Makefile中定義的變量增加一些變量。

#linux-3.5/drivers/char/Makefile
obj-$(CONFIG_TINY4412_LEDS)     += tiny4412_leds.o
obj-$(CONFIG_TINY4412_HELLO_MODULE)     += tiny4412_hello_module.o
obj-$(CONFIG_TINY4412_BUTTONS)  += tiny4412_buttons.o
obj-$(CONFIG_TINY4412_BUZZER)   += tiny4412_pwm.o
obj-$(CONFIG_TINY4412_BACKLIGHT)+= tiny4412_backlight.o
obj-$(CONFIG_TINY4412_ADC)              += tiny4412_adc.o

鏈接方式:

對於ARM體系,連接腳本就是arch/arm/kernel/vmlinux.lds,它由 arch/arm/kernel/vmlinux/lds.S文件生成。

6.向內核中添加新模塊

無論是向內核中添加新的功能還是驅動程序,都需要將相應的代碼添加到內核構建系統中,需要完成以下三個工作:

①將編寫的源碼復制到Linux內核源碼相應的目錄下

②在目錄的Kconfig文件中添加新源碼對應項目的編譯配置選項

③在目錄Makefile文件中增加對新源碼的編譯條目

下面以剛才的Led驅動為例來說明

①將編寫的源碼復制到Linux內核源碼相應的目錄下

②在目錄的Kconfig文件中添加新源碼對應項目的編譯配置選項

③在目錄Makefile文件中增加對新源碼的編譯條目

 


免責聲明!

本站轉載的文章為個人學習借鑒使用,本站對版權不負任何法律責任。如果侵犯了您的隱私權益,請聯系本站郵箱yoyou2525@163.com刪除。



 
粵ICP備18138465號   © 2018-2025 CODEPRJ.COM