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

来源:http://www.cnblogs.com/CrazyCatJack/archive/2016/12/01/6121231.html
-Advertisement-
Play Games

Hi,大家好!我是CrazyCatJack。最近在學習Linux內核的配置、編譯及Makefile文件。今天總結一下學習成果,分享給大家^_^ 1.解壓縮打補丁 首先是解壓縮你獲取到的Linux內核。這裡我用到的是linux.2.22.6版本的內核。在Linux下命令行通過tar xjf linux ...


  Hi,大家好!我是CrazyCatJack。最近在學習Linux內核的配置、編譯及Makefile文件。今天總結一下學習成果,分享給大家^_^

1.解壓縮打補丁

  首先是解壓縮你獲取到的Linux內核。這裡我用到的是linux.2.22.6版本的內核。在Linux下命令行通過tar xjf linux.2.22.6.tar.bz2解壓內核。然後,如果你需要對這個內核打補丁的話,用patch命令:patch -px <../linux.2.22.6.patch。這裡的px指的是忽略掉補丁文件中描述的第幾個斜杠。也就是忽略前x個目錄。

 

--- linux-2.6.22.6/arch/arm/configs/s3c2410_defconfig
+++ linux-2.6.22.6_jz2440/arch/arm/configs/s3c2410_defconfig

  如果你此刻就在內核的根目錄下,即linux-2.6.22.6下,也就是說打補丁需要忽略掉一個斜杠的目錄。那麼打補丁的命令就是patch -p1 <../linux.2.22.6.patch。

 

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

  3>include/config/auto.conf

  4>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'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內核的從配置到編譯的全部分析了^_^

 

 

 

                 

 

CCJ

2016-12-01 11:32:45

 

 

 

 

 

 


您的分享是我們最大的動力!

-Advertisement-
Play Games
更多相關文章
  • 在TSQL中,使用Pivot和Unpivot運算符將一個關係表轉換成另外一個關係表,兩個命令實現的操作是“相反”的,但是,pivot之後,不能通過unpivot將數據還原。這兩個運算符的操作數比較複雜,記錄一下自己的總結,以後用到時,作為參考。 一,Pivot用法 Pivot旋轉的作用,是將關係表( ...
  • 一、MySQL許可權系統通過兩個階段進行認證: (A) 對用戶進行身份認證,IP地址和用戶名聯合, (B) 對合法用戶賦予相應許可權,許可權表在資料庫啟動的時候載入記憶體中。 二、在許可權的存取過程中,會用到”mysql“資料庫中的user、host和db這3個許可權表。兩階段驗證過程 (A) user表中 h ...
  • rpm -qa |grep vsftpd yum search vsftpd yum install vsftpd 查看是否已經啟動: service vsftpd status 啟動: service vsftpd start 在瀏覽器中輸入地址訪問:記得在之前關閉防火牆 點擊我的電腦,在地址欄輸 ...
  • 創建xiangkejin zhangsan兩個用戶 可看見文件中創建的兩個用戶: 建立虛擬目錄並配置用戶認證 ①建立虛擬目錄 /xiangkejin ②在Apache的主配置文件httpd.conf文件中,加入以下語句 Alias /xiangkejin "/xkj"<Directory "/xkj ...
  • 1.安裝FTP服務 滑鼠桌面右擊個性化-卸載程式-打開或關閉windows功能 2.在IIS控制面板里添加FTP站點 下一步 下一步 滑鼠右擊 下一步 下一步 3.配置ftp站點 4.測試站點是否正常工作 ftp://192.168.1.101 ...
  • 查詢是否安裝了apache rpm -qa |grep httpd yum install httpd 安裝 service httpd start 啟動 測試Apache伺服器 註意:防火牆的配置 這是預設的防火牆策略,應該從瀏覽器訪問能夠通過,可是還是被擋了,當我iptables -F清除所有規 ...
  • ...
  • Memcached 是一個高性能的分散式記憶體對象緩存系統,用於動態Web應用以減輕資料庫負載。它通過在記憶體中緩存數據和對象來減少讀取資料庫的次數,從而提高動態、資料庫驅動網站的速度。Memcached基於一個存儲鍵/值對的hashmap。其守護進程(daemon )是用C寫的,但是客戶端可以用任何語... ...
一周排行
    -Advertisement-
    Play Games
  • 移動開發(一):使用.NET MAUI開發第一個安卓APP 對於工作多年的C#程式員來說,近來想嘗試開發一款安卓APP,考慮了很久最終選擇使用.NET MAUI這個微軟官方的框架來嘗試體驗開發安卓APP,畢竟是使用Visual Studio開發工具,使用起來也比較的順手,結合微軟官方的教程進行了安卓 ...
  • 前言 QuestPDF 是一個開源 .NET 庫,用於生成 PDF 文檔。使用了C# Fluent API方式可簡化開發、減少錯誤並提高工作效率。利用它可以輕鬆生成 PDF 報告、發票、導出文件等。 項目介紹 QuestPDF 是一個革命性的開源 .NET 庫,它徹底改變了我們生成 PDF 文檔的方 ...
  • 項目地址 項目後端地址: https://github.com/ZyPLJ/ZYTteeHole 項目前端頁面地址: ZyPLJ/TreeHoleVue (github.com) https://github.com/ZyPLJ/TreeHoleVue 目前項目測試訪問地址: http://tree ...
  • 話不多說,直接開乾 一.下載 1.官方鏈接下載: https://www.microsoft.com/zh-cn/sql-server/sql-server-downloads 2.在下載目錄中找到下麵這個小的安裝包 SQL2022-SSEI-Dev.exe,運行開始下載SQL server; 二. ...
  • 前言 隨著物聯網(IoT)技術的迅猛發展,MQTT(消息隊列遙測傳輸)協議憑藉其輕量級和高效性,已成為眾多物聯網應用的首選通信標準。 MQTTnet 作為一個高性能的 .NET 開源庫,為 .NET 平臺上的 MQTT 客戶端與伺服器開發提供了強大的支持。 本文將全面介紹 MQTTnet 的核心功能 ...
  • Serilog支持多種接收器用於日誌存儲,增強器用於添加屬性,LogContext管理動態屬性,支持多種輸出格式包括純文本、JSON及ExpressionTemplate。還提供了自定義格式化選項,適用於不同需求。 ...
  • 目錄簡介獲取 HTML 文檔解析 HTML 文檔測試參考文章 簡介 動態內容網站使用 JavaScript 腳本動態檢索和渲染數據,爬取信息時需要模擬瀏覽器行為,否則獲取到的源碼基本是空的。 本文使用的爬取步驟如下: 使用 Selenium 獲取渲染後的 HTML 文檔 使用 HtmlAgility ...
  • 1.前言 什麼是熱更新 游戲或者軟體更新時,無需重新下載客戶端進行安裝,而是在應用程式啟動的情況下,在內部進行資源或者代碼更新 Unity目前常用熱更新解決方案 HybridCLR,Xlua,ILRuntime等 Unity目前常用資源管理解決方案 AssetBundles,Addressable, ...
  • 本文章主要是在C# ASP.NET Core Web API框架實現向手機發送驗證碼簡訊功能。這裡我選擇是一個互億無線簡訊驗證碼平臺,其實像阿裡雲,騰訊雲上面也可以。 首先我們先去 互億無線 https://www.ihuyi.com/api/sms.html 去註冊一個賬號 註冊完成賬號後,它會送 ...
  • 通過以下方式可以高效,並保證數據同步的可靠性 1.API設計 使用RESTful設計,確保API端點明確,並使用適當的HTTP方法(如POST用於創建,PUT用於更新)。 設計清晰的請求和響應模型,以確保客戶端能夠理解預期格式。 2.數據驗證 在伺服器端進行嚴格的數據驗證,確保接收到的數據符合預期格 ...