Exynos4412 核心移植(二)—— 核心編譯過程分析

zqixiao_09發表於2016-03-07

核心的編譯同樣是從Makefile 來分析:

一、核心原始碼結構

Linux核心檔案數目近2萬,出去其他架構CPU的相關檔案,他們分別位於頂層目錄下的17個子目錄,各個目錄功能獨立,下面是常用目錄:

arch:體系結構相關程式碼
ipc:程式排程相關程式碼
mm:記憶體管理
Documentation:幫助文件
net:網路協議
lib:庫
scripts:編譯相關指令碼工具
tools:編譯相關工具
drivers:裝置驅動
fs:檔案系統實現


對於ARM 架構的Exynos4412,其體系相關的程式碼在arch/arm/目錄下,在後面進行的Linux移植時,開始的工作正式修改這個目錄下的檔案。


二、Linux Makefile分析

核心中的哪些檔案將被編譯?它們是怎樣被編譯的?它們連線時的順序如何確定?那個檔案在最前面?哪些檔案或函式先執行?這些都是通過Makefile 來管理的。從最簡單的角度來總結Makefile的作用,有以下3點:

1)-- 決定編譯哪些檔案;

2)-- 怎樣編譯這些檔案?

3)-- 怎樣連線這些檔案,最重要的是它們的順序如何?

Linux 核心原始碼中含有很多個Makefile檔案,這些Makefile檔案又要包含其他一些檔案(比如配置資訊、通用的規則等)。這些檔案構成了 Linux 的Makefile 體系,可以分為下表中的5類:

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


以下根據見面總結的Makefile 的3大作用分析這5類檔案。

1、決定編譯哪些檔案

Linux核心的編譯過程從頂層Makefile開始,然後遞迴地進入各級子目錄呼叫他們的makefile,分為3個步驟:

a -- 頂層Makefile 決定核心根目錄下哪些子目錄將被編進核心;

b -- arch/$(ARCH)/Makefile 決定arch/$(ARCH)目錄下哪些檔案、哪些目錄將被編進核心;

c -- 各級子目錄下的Makefile決定所在目錄下哪些檔案將被編進核心,哪些檔案將被程式設計模組(即驅動程式),進入哪些子目錄繼續呼叫它們的Makefile。


a -- 先看步驟a, 頂層Makefile的編譯

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

可見,頂層Makefile將這14個子目錄分為5類:init-y、divers-y、net-y、libs-y和core-y

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

對於ARCH變數,可以在執行make時傳入,比如“make ARCH=arm ...”。另外,對於非X86平臺,還需要指定交叉編譯工具,這也可以在執行make 命令時傳入,比如“make CROSS_COPILE=arm-linux- ..”。為了方便,常在頂層Makefile中進行如下修改這樣執行make時就會將ARCH變數傳入



b -- 看步驟 b,arch/$(ARCH)/Makefile的編譯

對於步驟 b 的 arch/$(ARCH)/Makefile,以ARM為例,在arch/arm/Makefile 中可以看到如下內容:


從129行可知,除了剛面的5類子目錄外,又出現了一類:head-y,不過它直接以檔名出現;

arch/arm/Makefile 中類似第268-273行的程式碼進一步擴充套件了core-y的內容,第276行擴充套件了libs-y的內容,這些都是體系相關的目錄;第261-265行中的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


c -- 步驟 c 是如何進行的,各級子目錄下的Makefile的編譯

在配置核心時,生成配置檔案.config。核心頂層Makefile使用如下語句間接包含.config 檔案,以後就根據.config中定義的各個變數決定編譯哪些檔案。值所以說是“間接”包含,試音為包含的是include/config/auto.conf 檔案,而它只是將.config檔案中的註釋去掉,並根據頂層Makefile中定義的變數增加一些變數而已。



2、怎樣編譯這些檔案

即編譯選項、連線選項是什麼。這些選項分3類:全域性的,適用於整個核心程式碼樹;區域性的,僅適用於某個Makefile中的所有檔案;個體的,僅適用於某個檔案。

全域性選項在頂層Makefile和arch/$(ARCH)/Makefile 中定義,這些選項的名稱為:CFLAGS、AFLAGS、LDFLAGS、ARFLAGS,他們分別是編譯C檔案的選項、編譯彙編問價你的選項、連線檔案的選項、製作庫檔案的選項。


3、怎樣連線這些檔案,它們順序如何

前面分析有哪些檔案要編進核心時,頂層Makefile和arch/$(ARCH)/Makefile定義了6類目錄(或檔案):head-y、init-y、drivers、libs-y 和 core-y。它們的初始值如下(以ARM體系為例)

arch/arm/Makefile 中:



頂層makefile 中:



可見,除head-y 外,其餘的init-y、drivers-y等都是目錄名。在頂層Makefile 中,這IE目錄名的後面直接加上built-in.o 或 lib.a,表示要連線進核心的檔案。


上面的patubst是個字串處理函式,它的用法如下:

(patsubst pattern, replacement,text)

表示尋找“text”中符合格式“pattern”的字,用”replacement"替換它們。比如上面的init-y初值為“init/”,經過793行的互動後,“init-y” 變為“init/built - in.o”。


頂層Makefile中,再往下看:



對於ARM體系,連線指令碼就是arch/arm/kernel/vmlinux.lds,它由 arch/arm/kernel/vmlinux/lds.S檔案生成,先將生成的arch/arm/kernel/vmlinux.lds摘錄如下:



總結:

a -- 配置檔案.config 中定義了一系列的變數,Makefile將結合它們來決定哪些檔案被編進核心、哪些檔案被編進模組、涉及哪些子目錄;

b -- 頂層Makefile和arch/$(ARCH)/Makefile決定根目錄下哪些子目錄、arch/$(ARCH) 目錄下哪些檔案和目錄將被編進核心;

c -- 最後,各級子目錄下的Makefile決定所在目錄下哪些檔案將被編進核心,哪些檔案將被變成模組(即驅動程式),進入哪些子目錄繼續呼叫它們的Makefile;

d -- 頂層Nakedfile和arch/$(ARCH)/Makefile設定了可以影響所有檔案的編譯、連線選項:CFLAGS、AFLAGS、LDFLAGS、ARFLAGS;

e -- 頂層Makefile按照一定的順序組織檔案,根據連線指令碼 arch/$(ARCH)/kernel/vmlinux.lds生成核心映像檔案vmlinux。



相關文章