tft每日頭條

 > 圖文

 > linux編譯内核

linux編譯内核

圖文 更新时间:2024-09-29 08:05:39

linux編譯内核?a) 首先,你要有一台PC(這不廢話麼^_^),裝好了linux,我來為大家科普一下關于linux編譯内核?以下内容希望對你有幫助!

linux編譯内核(手把手教你編譯Linux内核)1

linux編譯内核

準備工作

a) 首先,你要有一台PC(這不廢話麼^_^),裝好了linux。

b) 安裝好GCC(這個指的是host gcc,用于編譯生成運行于pc機程序的)、make、ncurses等工具。

c) 下載一份純淨的Linux内核源碼包,并解壓好。

注意,如果你是為當前PC機編譯内核,最好使用相應的Linux發行版的源碼包。

嵌入式進階教程分門别類整理好了,看的時候十分方便,由于内容較多,這裡就截取一部分圖吧。

需要的朋友私信【内核】即可領取。

内核學習地址:Linux内核源碼/内存調優/文件系統/進程管理/設備驅動/網絡協議棧-學習視頻教程-騰訊課堂

不過這應該也不是必須的,因為我在我的Fedora 13上(其自帶的内核版本是2.6.33.3),就下載了一個标準的内核linux-2.6.32.65.tar.xz,并且順利的編譯安裝成功了,上電重啟都OK的。不過,我使用的.config配置文件,是Fedora 13自帶内核的配置文件,即/lib/modules/`uname -r`/build/.config

d) 如果你是移植Linux到嵌入式系統,則還要再下載安裝交叉編譯工具鍊。

例如,你的目标單闆CPU可能是arm或mips等CPU,則安裝相應的交叉編譯工具鍊。安裝後,需要将工具鍊路徑添加到PATH環境變量中。例如,你安裝的是arm工具鍊,那麼你在shell中執行類似如下的命令,假如有類似的輸出,就說明安裝好了。

[root@localhost linux-2.6.33.i686]# arm-linux-gcc --version arm-linux-gcc (Buildroot 2010.11) 4.3.5Copyright (C) 2008 Free Software Foundation, Inc.This is free software; see the source for copying conditions. There is NOwarranty; not even for MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.

設置編譯目标

在配置或編譯内核之前,首先要确定目标CPU架構,以及編譯時采用什麼工具鍊。這是最基礎的信息,首先要确定的。

如果你是為當前使用的PC機編譯内核,則無須設置。

否則的話,就要明确設置。

這裡以arm為例,來說明。

有兩種設置方法():

a) 修改makefile

打開内核源碼根目錄下的Makefile,修改如下兩個Makefile變量并保存。

ARCH := armCROSS_COMPILE := arm-linux-

注意,這裡cross_compile的設置,是假定所用的交叉工具鍊的gcc程序名稱為arm-linux-gcc。如果實際使用的gcc名稱是some-thing-else-gcc,則這裡照葫蘆畫瓢填some-thing-else-即可。總之,要省去名稱中最後的gcc那3個字母。

b) 每次執行make命令時,都通過命令行參數傳入這些信息。

這其實是通過make工具的命令行參數指定變量的值。

例如:

  • 配置内核時,使用make ARCH=arm CROSS_COMPILE=arm-linux- menuconfig

  • 編譯内核時使用make ARCH=arm CROSS_COMPILE=arm-linux-

    注意,實際上,對于編譯PC機内核的情況,雖然用戶沒有明确設置,但并不是這兩項沒有配置。因為如果用戶沒有設置這兩項,内核源碼頂層Makefile(位于源碼根目錄下)會通過如下方式生成這兩個變量的值。

    SUBARCH := $(shell uname -m | sed -e s/i.86/i386/ -e s/sun4u/sparc64/ \-e s/arm.*/arm/ -e s/sa110/arm/ \-e s/s390x/s390/ -e s/parisc64/parisc/ \-e s/ppc.*/powerpc/ -e s/mips.*/mips/ \-e s/sh[234].*/sh/ ) ARCH?= $(SUBARCH)CROSS_COMPILE ?=

    經過上面的代碼,ARCH變成了PC編譯機的arch,即SUBARCH。因此,如果PC機上uname -m輸出的是ix86,則ARCH的值就成了i386。

    而CROSS_COMPILE的值,如果沒配置,則為空字符串。這樣一來所使用的工具鍊程序的名稱,就不再有類似arm-linux-這樣的前綴,就相當于使用了PC機上的gcc。

    最後再多說兩句,ARCH的值還需要再進一步做泛化。因為内核源碼的arch目錄下,不存在i386這個目錄,也沒有sparc64這樣的目錄。

    因此頂層makefile中又構造了一個SRCARCH變量,通過如下代碼,生成他的值。這樣一來,SRCARCH變量,才最終匹配到内核源碼arch目錄中的某一個架構名。

    SRCARCH := $(ARCH) ifeq ($(ARCH),i386) SRCARCH := x86endif ifeq ($(ARCH),x86_64) SRCARCH := x86endififeq ($(ARCH),sparc64) SRCARCH := sparcendififeq ($(ARCH),sh64) SRCARCH := shendif

    配置内核

    内核的功能那麼多,我們需要哪些部分,每個部分編譯成什麼形式(編進内核還是編成模塊),每個部分的工作參數如何,這些都是可以配置的。因此,在開始編譯之前,我們需要構建出一份配置清單,放到内核源碼根目錄下,命名為.config文件,然後根據此.config文件,編譯出我們需要的内核。

    但是,内核的配置項太多了,一個一個配,太麻煩了。而且,不同的CPU架構,所能配置的配置項集合,是不一樣的。例如,某種CPU的某個功能特性要不要支持的配置項,就是與CPU架構有關的配置項。所以,内核提供了一種簡單的配置方法。

    以arm為例,具體做法如下。

    a) 根據我們的目标CPU架構,從内核源碼arch/arm/configs目錄下,找一個與目标系統最接近的配置文件(例如s3c2410_defconfig),拷貝到内核源碼根目錄下,命名為.config。

    注意,如果你是為當前PC機編譯内核,最好拷貝如下文件到内核源碼根目錄下,做為初始配置文件。這個文件,是PC機當前運行的内核編譯時使用的配置文件。

    /lib/modules/`uname -r`/build/.config

    這裡順便多說兩句,PC機内核的配置文件,選擇的功能真是多。不編不知道,一編才知道。Linux發行方這樣做的目的,可能是想讓所發行的Linux能夠滿足用戶的各種需求吧。

    b) 執行make menuconfig對此配置做一些需要的修改,退出時選擇保存,就将新的配置更新到.config文件中了。

    注意-1,我們執行此操作時,内核打開了一組配置項集合,讓我們進行配置。這一組配置項集合,是由我們前面設置的CPU架構決定的。說得細一點,配置系統打開arch/arm/Kconfig文件(make menuconfig執行時能看到有一行“scripts/kconfig/mconf arch/arm/Kconfig”這樣的打印),這個文件又包含了其他内核子系統的Kconfig文件(文件名也可能是其他名字),其他子系統的Kconfig文件,再層層包含下層的Kconfig文件,從而生成了全部的配置項集合。而每一項配置項,當前設定的值(例如,是編進内核,還是編譯成模塊,或者也可能是一項參數),則是由内核源碼根目錄下的.config文件生成的。

    注意-2,即使你不需要對配置進行任何修改,都務必請執行一下make menuconfig,然後進入配置界面後直接退出并保存。不然的話,後面的編譯可能會遇到問題。筆者就遇到過這個問題。筆者猜測原因可能是,初始的配置文件是基于老版本的内核做的,新版本的内核可能新增了一些基礎功能項,從而導緻功能項之間的依賴關系發生了變化。例如,老的配置文件中選中的一個功能項,在新版内核中的實現,可能依賴了更多的其他功能項。因此需要對舊的初始配置文件進行一些調整,從而保證各個功能項的依賴條件得到滿足。經過make menuconfig之後,筆者發現,.config文件的内容的确發生了變化。

    編譯内核

    編譯本身很簡單,對于2.6版本以上的内核,執行如下一條命令就搞定了。

    我們不妨花點時間,理解一下内核編譯的機制。

    a) 内核如何使用config文件

    前面生成了.config文件,這是個文本文件,其中都是一些類似如下的内容:

    CONFIG_YENTA_ENE_TUNE=yCONFIG_YENTA_TOSHIBA=yCONFIG_PD6729=mCONFIG_I82092=m CONFIG_MTDRAM_ERASE_SIZE=128

    能看出,有些是設置了将某個功能編譯進内核,有些是設置了将某個功能編譯成模塊,有些是設置了某個功能的某個參數。

    這個文件的語法,其實就是定義makefile變量的語法。沒錯,這就是makefile。

    當我們執行make開始編譯内核的時候,編譯系統還會生成另一個config文件,那就是include/config/auto.conf。裡面的内容和.config類似,隻是内容少了一些。

    内核編譯的時候,頂層Makefile(位于源碼根目錄下),會包含上述config文件。

    這樣就獲得了相應的makefile變量,從而知道如何編譯内核的各個部分。

    從頂層makefile中,可以看到如下代碼:

    ifeq ($(dot-config),1)# Read in config-include include/config/auto.conf

    但是,這兩個config文件的關系如何,到底會包含哪個,在下也沒有理清...

    b) 内核如何編譯各個子系統或模塊

    從上一步知道,通過config文件,内核頂層makefile已經生成了大量的makefile變量。

    另一方面,每個子系統或模塊,他們的源碼目錄中,都有一個Makefile,其中定義了本子系統或模塊所需要編譯的内容。

    接下來,make工具就可以帶着頂層makefile中生成的大量的makefile變量,一層層進入到各個子系統或模塊所在的目錄中去,去實現各目錄中Makefile中定義的内容的編譯。

    而這些目錄中的Makefile可以說是非常簡單。

    如果某個目錄下,隻有一個模塊hello,此模塊隻有一個.c文件,例如xxx.c。那麼其Makefile的全部内容隻有如下一行。

    obj-$(CONFIG_HELLO) := hello.o

    如果hello模塊,由main.c a.c b.c三個文件構成,則Makefile也隻需要兩行内容。

    obj-$(CONFIG_HELLO) := hello.o

    hello-objs := main.o a.o b.o

    如果一個目錄下存放了多個模塊的C文件,别是hello、hello2、hello3。hello模塊的構成:main.c a.c b.chello2模塊的構成:main2.c a2.c b2.chello3模塊的構成:hello3.c此時,Makefile隻需要5行内容。

    obj-$(CONFIG_HELLO) = hello.o obj-$(CONFIG_HELLO2) = hello2.o obj-$(CONFIG_HELLO3) = hello3.o hello-objs := main.o a.o b.ohello2-objs := main2.o a2.o b2.o

    由于頂層Makefile中帶有大量的變量,因此,子目錄内Makefile中的$(CONFIG_HELLO)變量經過解析後,會變成y或m。這樣的話,每個子目錄中的Makefile經過解析後,等于隻是定義了一個變量,變量名為obj-m或obj-y。

    變量obj-m或obj-y的值,則是一串.o文件的列表。表中每一項,代表一個功能項。如果變量名為obj-m,則此功能被編譯成模塊。如果變量名為obj-y,則此功能被編進内核。

    c) 内核代碼中,如何知道某個功能有沒有配置,配置成了什麼形式

    當我們執行make開始編譯内核的時候,編譯系統還會生成一個C語言頭文件

    include/generated/autoconf.h

    這個文件中都是類似如下的内容:

    #define CONFIG_DM9000 1 #define CONFIG_DM9000_DEBUGLEVEL 4 #define CONFIG_SND_RAWMIDI_SEQ_MODULE 1

    第一行,是說明用戶選擇了将DM9000這個驅動編進内核,第二行是此驅動的一個參數。如果用戶選擇的是将DM9000編譯成模塊,則第一行的内容就變成如下形式了。

    #define CONFIG_DM9000_MODULE 1

    有了這個頭文件,某個内核源碼的.c文件中如果包含了這個頭文件,通過#ifdef CONFIG_XXX就可以知道用戶有沒有配置XXX功能了。

    好了,内核編譯機制,就講到這裡了^_^

    安裝内核

    a) 為當前PC機安裝内核

    依次執行如下兩條命令,分别完成模塊和内核的安裝。

    make modules_install make install

    然後打開boot/grub/grub.conf,會看到裡面多出了一個條目。

    将其中的timeout修改為5,以便開機時有5秒的時間選擇啟動哪一個内核。

    最後,重啟電腦。在bootloader界面出現時,選擇啟動新内核即可。

    b) 為嵌入式系統安裝内核

    這就不是一句兩句能說清的了,具體問題大家自己具體參考相關資料吧^_^

    對于一般的arm單闆,常見的方法是,PC機通過SecureCrt連接單闆串口,通過網線連接單闆網口,PC機上啟動tftp服務器,把内核映像zImage文件放到tftp下載目錄中。重啟單闆,SecureCrt中看到u-boot啟動倒計時的時候,按任意鍵進入u-boot交互界面。然後在這個界面下,通過相關命令下載内核映像zImage文件,然後通過命令将下載的zImage燒寫到單闆的FLASH中。最後重啟單闆即可。

    至于模塊的安裝,則很簡單,通過如下一條命令搞定

    make -C /path/to/kernel_src_dir modules_install INSTALL_MOD_PATH=/path/to/rootfs_dir

    上面的命令執行後,模塊就已經安裝到目标系統的根文件系統中了 。

    當然,上面的根文件系統隻是按一定的結構組織起來的一組目錄與文件,他還需要被打包成具體的文件系統格式(如CramFS,squashfs,jffs2等),然後燒寫到flash中才能最終使用^_^。

    更多精彩资讯请关注tft每日頭條,我们将持续为您更新最新资讯!

    查看全部
  • 相关圖文资讯推荐

    热门圖文资讯推荐

    网友关注

    Copyright 2023-2024 - www.tftnews.com All Rights Reserved