首頁  >  文章  >  php教程  >  Linux核心配置、編譯及Makefile簡述

Linux核心配置、編譯及Makefile簡述

高洛峰
高洛峰原創
2016-12-01 15:41:491576瀏覽

  Hi,大家好!我是CrazyCatJack。最近在學習Linux核心的設定、編譯及Makefile檔案。今天總結學習成果,分享給大家^_^

1.解壓縮打補丁

  首先是解壓縮你獲取到的Linux核心。這裡我用到的是linux.2.22.6版本的核心。在Linux下命令列透過tar xjf linux.2.22.6.tar.bz2解壓縮內核。然後,如果你需要對這個核心打補丁的話,用patch指令:patch -px <..>

 

--- linux-2.6.22.6/arch/arm/configs/s3c2410_defconfig+++ linux-2.6.22.6_jz2440/arch/arm/configs/s3c2.6.22.6_jz2440/arch/arm/configs/s3c2410_definc2410_L3c2410_L3c2410_deflin. -2.6.22.6下,也就是說打補丁需要忽略掉一個斜線的目錄。那麼打補丁的指令就是patch -p1 <..>

 

2.配置核心

  現在補丁已經打好了,接下來就是配置核心了。這裡配置有3種方法:

  1>直接進行make menuconfig。這是最麻煩的一種方法,所有的配置都需要你來操作。

  2>在預設設定上自己修改,也就是修改defconfig檔。使用 find -name "*defconfig*"尋找你的架構對應的預設設定檔。我是在arch/arm/configs找到自己板子的預設設定檔。執行defconfig檔: make XXX_defconfig。 XXX是你具體使用的板子型號。執行此操作後,結果會儲存在.config檔。然後再執行make menuconfig指令。這時的配置就是在預設配置上稍加修改就可以了。

  3>使用廠商的設定檔。如果你的硬體有廠商提供的config檔那是最輕鬆的。直接cp XXX .config。然後執行make menuconfig。

  這裡詳細跟大家講一下內核的配置。 Linux的核心配置,就是為了產生.config檔。因為在編譯時需要用.config檔產生其他相關設定檔。我們的配置項目大多是例如CONFIG_XXXDRIVER,這裡的XXXDRIVER指的是各種驅動。我們需要告訴內核,這些驅動是編譯進內核,還是編譯成模組。透過尋找CONFIG_XXXDRIVER,我們可以發現,它出現在四個地方:

  1>C原始碼

  2>子目錄Makefile:drivers/XXX/Makefile

 〜『34d/po『 include/linux/autoconf.h

    這裡首先說明:.config檔在進行核心編譯時(make uImage)產生了include/config/auto.conf和include/linux/autoconf.h。透過查看C原始碼我們發現CONFIG_XXXDRIVER是一個巨集定義,等於一個常數。在include/linux/autoconf.h中宏定義CONFIG_XXXDRIVER為常數,可能是0或1。那現在有個問題,就是CONFIG_XXXDRIVER到底被編譯進核心還是編譯成模組呢?這在C語言中是無法區分的,而這種區分體現在哪裡呢?這種區分體現在子目錄的Makefile檔案中。在子目錄的Makefile中,若有 obj -y += XXX.o則表示XXX.c被編譯進核心;obj -m +=XXX.o則表示XXX被編譯成模組,為XXX.ko。 include/config/auto.conf檔則是對CONFIG_XXXDRIVER進行賦值,為y時表示編譯進內核,為m時表示編譯成獨立模組。

#这里是include/config/auto.conf的部分内容
# Automatically generated make config: don&#39;t edit
# Linux kernel version: 2.6.22.6
# Sun Nov 27 18:34:38 2016
#
CONFIG_CPU_S3C244X=y
CONFIG_CPU_COPY_V4WB=y
CONFIG_CRYPTO_CBC=y
CONFIG_CPU_S3C2410_DMA=y
CONFIG_CRYPTO_ECB=m
CONFIG_SMDK2440_CPU2440=y
#这里是drivers/i2c/Makefile
# Makefile for the i2c core.
#

obj-$(CONFIG_I2C_BOARDINFO)    += i2c-boardinfo.o
obj-$(CONFIG_I2C)        += i2c-core.o
obj-$(CONFIG_I2C_CHARDEV)    += i2c-dev.o
obj-y                += busses/ chips/ algos/

ifeq ($(CONFIG_I2C_DEBUG_CORE),y)
EXTRA_CFLAGS += -DDEBUG
endif

3.編譯核心

  透過上面的描述,我們可以知道,在每個driver下,都有一個Makefile檔。來定義這個驅動是編譯進核心還是編譯成模組。這裡稍稍提一下。上面我們講到了在Makefile中單一檔案怎麼編譯進核心和編譯成模組。但是如果有兩個以上的文件該如何書寫呢?這裡舉個例子:obj -y += a.o b.o就表示將a.c和b.c編譯進核心。

obj -m += ab.o

ab -objs := a.o b.o

就可以表示將a.c和b.c共同編譯成模組。過程是 a.c生成a.o , b.c生成b.o。 a.o 和b.o共同產生ab.ko。在以往的uboot啟動核心的程式碼分析中,我們提到編譯核心產生的uImage是由兩個部分組成的:頭部+Linux核心。這個頭部包含了很多初始化的參數訊息,例如核心的載入位址和入口位址。在編譯核心時,我們直接執行make uImage即可。那麼在檔案中是怎麼定義uImage的呢?又是怎麼生成uImage的呢?

  首先,我們透過尋找Makefile,發現uImage在arch/arm/Makefile中,而這個架構目錄下的Makefile被包含進頂層目錄的Makefile中。這樣我們在執行 make uImage時,頂層目錄的Makefile就可以呼叫架構子目錄下的Makefile,實現對核心的編譯,產生uImage。

 顶层目录下Makefile中相关命令:
include $(srctree)/arch/$(ARCH)/Makefile
架构目录下Makefile相关命令:
zImage Image xipImage bootpImage uImage: vmlinux

  這就是剛剛所說的頂層Makefile呼叫架構目錄下Makefile,架構目錄下Makefile產生uImage,而且依賴於vmlinux檔。下面我們就開始講解如何產生vmlinux檔。在頂層Makefile中,我們找到了有關生成vmlinux的大部分命令。

顶层目录Makefile:
init-y        := init/
init-y        := $(patsubst %/, %/built-in.o, $(init-y)) 

core-y        := usr/
core-y        += kernel/ mm/ fs/ ipc/ security/ crypto/ block/
core-y        := $(patsubst %/, %/built-in.o, $(core-y)) 

libs-y        := lib/
libs-y1        := $(patsubst %/, %/lib.a, $(libs-y))
libs-y2        := $(patsubst %/, %/built-in.o, $(libs-y))
libs-y        := $(libs-y1) $(libs-y2) 

drivers-y    := drivers/ sound/
drivers-y    := $(patsubst %/, %/built-in.o, $(drivers-y))   

net-y        := net/
net-y        := $(patsubst %/, %/built-in.o, $(net-y)) = net/built-in.o


vmlinux: $(vmlinux-lds) $(vmlinux-init) $(vmlinux-main) $(kallsyms.o) FORCE

vmlinux-init := $(head-y) $(init-y)
vmlinux-main := $(core-y) $(libs-y) $(drivers-y) $(net-y)
vmlinux-all  := $(vmlinux-init) $(vmlinux-main)
vmlinux-lds  := arch/$(ARCH)/kernel/vmlinux.lds
export KBUILD_VMLINUX_OBJS := $(vmlinux-all)



架构目录Makefile:
zImage Image xipImage bootpImage uImage: vmlinux

head-y        := arch/arm/kernel/head$(MMUEXT).o arch/arm/kernel/init_task.o

  我已经把顶层目录和架构目录下生成vmlinux的命令摘选出来。首先,我们看要想生成vmlinux,需要vmlinux-lds文件、vmlinux-init文件、vmlinux-main文件。其中,vmlinux-lds是链接脚本文件,定义了代码段,数据段的存放位置。这里我们接着往下看,vmlinux-init需要head-y和init-y,通过查看两个Makefile,我们可以得到经过转换后的结果:

head-y        := 
arch/arm/kernel/head$(MMUEXT).o    arch/arm/kernel/init_task.o

init-y        := $(patsubst %/, %/built-in.o, $(init-y)) = init/built-in.o

core-y        := $(patsubst %/, %/built-in.o, $(core-y)) 
                         = usr/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

libs-y        := $(libs-y1) $(libs-y2) =lib/lib.a lib/built-in.o

drivers-y    := $(patsubst %/, %/built-in.o, $(drivers-y)) = drivers/built-in.o  sound/built-in.o  

net-y        := $(patsubst %/, %/built-in.o, $(net-y)) = net/built-in.o

  现在已经分析了内核编译的全部过程。那怎样知道我们分析的到底对不对,通过实际执行make uImage我们就可以看到执行过程。这是执行make uImage过程中的部分相关命令:

arm-linux-ld -EL  -p --no-undefined -X -o vmlinux 
-T arch/arm/kernel/vmlinux.lds 
arch/arm/kernel/head.o 
arch/arm/kernel/init_task.o  init/built-in.o --start-group  usr/built-in.o  arch/arm/kernel/built-in.o  arch/arm/mm/built-in.o

  可以看到,首先目标要生成vmlinux,然后是链接脚本为vmlinux.lds。开始生成第一个文件:head.o,第二个文件:init_task.o。这和我们分析的完全一致。接下来以此类推,和我们分析的相同,也就是说我们分析的是正确的。

SECTIONS
{



 . = (0xc0000000) + 0x00008000;

 .text.head : {
  _stext = .;
  _sinittext = .;
  *(.text.head)
 }

 .init : { /* Init code and data        */
   *(.init.text)
  _einittext = .;
  __proc_info_begin = .;
   *(.proc.info.init)
  __proc_info_end = .;
  __arch_info_begin = .;
   *(.arch.info.init)
  __arch_info_end = .;
  __tagtable_begin = .;
   *(.taglist.init)
  __tagtable_end = .;
  . = ALIGN(16);
  __setup_start = .;
   *(.init.setup)
  __setup_end = .;
  __early_begin = .;
   *(.early_param.init)
  __early_end = .;
  __initcall_start = .;

  这是链接脚本vmlinux.lds中的部分内容。首先定义了虚拟地址:(0xc0000000) + 0x00008000。 然后是首先执行头部文件,这与我们分析的完全一致。代码段,初始化代码段等等。

  这就是Linux内核的从配置到编译的全部分析了^_^


陳述:
本文內容由網友自願投稿,版權歸原作者所有。本站不承擔相應的法律責任。如發現涉嫌抄襲或侵權的內容,請聯絡admin@php.cn