在Ubuntu上編譯安裝linux內核詳細過程


 

Ubuntu上編譯安裝linux內核詳細過程

 

時間:20220414,版本:V0.1

作者:robotech_erx

1.預備

1.1解釋題目

一個linux系統需要3個組件:內核、根文件系統、bootloader。不管是哪個發行版或者嵌入式系統,內核都是一樣的。Bootloader也相對簡單,pc上用grub,嵌入式系統上用uboot。比較麻煩的是構建根文件系統(init系統,GUI,編譯工具,shell,各種工具等等)。嵌入式系統上還好說,有很多的工具可以快速的搞出一個最小(或者不那么小的)根文件系統。PC上的根文件系統,工作量就很龐大了,不是那么快能完成的。其實一個發行版,比如ubuntu,叫做linux根文件系統更准確。

因此,這里僅僅是編譯一個新的內核並安裝,修改一下grub,讓他加載新的內核啟動系統。根文件系統還是Ubuntu原來的。

1.2關於linux內核版本號和Ubuntu版本號

查看當前linux內核版本

$ uname -r

5.13.0-39-generic

含義如下:major#.minor#[.patchlevel][-EXTRAVERSION]

對應到5.13.0-39-generic

5:主版本號

13:次版本號,一個次版本號出現通常代表着是一個穩定版本

0patchlevelapplied on occasion to the stable kernel when significant bug/security fixes are required.

-39-genericEXTRAVERSION,又稱作localversion,通常是發行版使用,用於標記發行版對內核的修改。

1.3發行版本和內核版本的對應關系

從版本號可以知道(-39-generic),發行版的內核與原版相比是有修改的。下載發行版的代碼可以參考:

https://wiki.ubuntu.com/Kernel/Dev/KernelGitGuide

https://cloud.tencent.com/developer/article/1439068 找到運行的Ubuntu版本對應的內核源碼

我們這里使用原始版本的代碼編譯一個內核,但是文件系統使用的還是ubuntu20.04的。Ubuntu版本和內核版本是有關聯的。例如ubuntu 20.04 里,apt-cache search linux-image查看。最舊的版本也是5.4。如果使用4.x的內核,可能會有一些問題(哪些問題呢?)。

2.編譯

2.1下載內核、安裝工具

這里編譯的版本是5.17.2。(原有版本是Linux version 5.13.0-39-generic)。

安裝需要的工具:

$sudo apt update

$sudo apt install git fakeroot build-essential ncurses-dev xz-utils libssl-dev bc flex libelf-dev bison dwarves

上面的工具編譯4.x的內核足夠了,但是5.13之后的還需要一些別的工具

sudo apt install zstd #5.13之后支持zstd壓縮

2.2獲取起始的.config文件

完全手工指定內核的配置選項不現實,一般都是找一個.config文件然后以這個文件為基礎進行修改。這個起始的配置文件一般3種獲取的方法:

1)使用源碼里自帶的defconfig文件。如果是嵌入式系統,使用已有的defconfig配置是個不錯的選擇。

2)可以使用Ubuntu20.04自己的config文件作為配置的基礎。

在源碼文件根目錄下:

$ cp /boot/config-$(uname -r) ./.config

直接復制問題是,一些新內核新增加的配置需要自己手工配置了。

3)使用localmodconfig 對象獲取一個精簡的編譯配置。

為了能夠應對各種各樣的環境,發布版的內核包含很多內核模塊。但是在某個特定機器,例如,大家自己平時使用的PC上實際用到的模塊只是其中的極小一部分。重新構建內核時,對不使用的模塊進行編譯就會浪費時間。

localmodconfig作為make的目標,kbuild系統會獲取一個當前在用的模塊的列表,生成僅以正在使用的內核模塊為對象的.config文件,從而大幅度減少編譯時間。

在源碼文件根目錄下:

lsmod > /tmp/lsmod.now

make LSMOD=/tmp/lsmod.now localmodconfig

Localmodconfig也是使用/boot/config-$(uname -r) ./.config作為基准的。輸入命令后,兩個kbuild會詢問對於新內核增加的那些配置的選擇。

這里使用的是第3種方法。

2.3配置menuconfig

$ make menuconfig

 

這里主要是想編一個可GDB調試的內核,所以有以下兩個配置:

 

1)在生成的vmlinux中保留調試信息:

 

Kernel hacking--->

Compile-time checks and compiler options  --->

[*] Compile the kernel with debug info  

[*] Provide GDB scripts for kernel debugging   

 

2)啟用KGDB/KDB支持:

 

Kernel hacking    --->

Generic Kernel Debugging Instruments   --->                                                                         

--- KGDB: kernel debugger                                    

[*]   KGDB: use kprobe blocklist to prohibit unsafe breakpoints        

<*>   KGDB: use kgdb over the serial console            

[ ]   KGDB: internal test suite                        

[*]   KGDB: Allow debugging with traps in notifiers    

[*]   KGDB_KDB: include kdb frontend for kgdb                         

(0x1)   KDB: Select kdb command functions to be enabled by default    

[*]     KGDB_KDB: keyboard as input device                         

(0)     KDB: continue after catastrophic errors                       

 

不同的內核版本中,具體的位置可能不太一樣。

不論是第2還是第3種方法設置的初始配置文件,上述2個配置都是默認選中的。所以這里僅僅是查看一下~

2.4編譯

make -j4            #使用4線程編譯

 

遇到一個出錯:

make[1]: *** No rule to make target 'debian/canonical-certs.pem', needed by 'certs/x509_certificate_list'.  Stop.

查了一下,需要關閉兩個配置

第一個是

CONFIG_SYSTEM_TRUSTED_KEYS="debian/canonical-certs.pem"

找到他修改成:

CONFIG_SYSTEM_TRUSTED_KEYS=""

或者運行腳本關閉:

scripts/config --disable SYSTEM_TRUSTED_KEYS

or

scripts/config --set-str SYSTEM_TRUSTED_KEYS ""

第二個是

CONFIG_SYSTEM_REVOCATION_KEYS="debian/canonical-revoked-certs.pem"

關閉:

scripts/config --disable SYSTEM_REVOCATION_KEYS

 

具體原理沒有深究。參考自:

(https://askubuntu.com/questions/1329538/compiling-the-kernel-5-11-11)

 

編譯完成后,顯示

...

Kernel: arch/x86/boot/bzImage is ready  (#2)

括號里的 #2意思是這個內核的第二次構建。

 

除了bzImage 其他生成的東西系包括:

vmlinux,比較大的文件(900MbzImage 不到10M

modules,以模塊方式編譯的驅動們。執行如下命令查看都生成了哪些模塊:

$ find . -name *.ko

 

2.5安裝內核、模塊和Initramfs

兩個make命令完成這個工作。

安裝模塊

$sudo make modules_install  #安裝模塊

“安裝”就是把模塊文件拷貝到根文件系統的目錄中,這里是/lib/modules/$(uname -r)/

 

需要注意的是:

ls -l /lib/modules/5.17.2/

total 384

lrwxrwxrwx  1 root root    34 4月  13 20:18 build -> /home/sunlion/Desktop/linux-5.17.2

drwxr-xr-x 10 root root  4096 4月  13 20:18 kernel

-rw-r--r--  1 root root 29941 4月  14 08:51 modules.alias

-rw-r--r--  1 root root 27556 4月  14 08:51 modules.alias.bin

-rw-r--r--  1 root root 10361 4月  13 20:18 modules.builtin

-rw-r--r--  1 root root 26092 4月  14 08:51 modules.builtin.alias.bin

-rw-r--r--  1 root root 12959 4月  14 08:51 modules.builtin.bin

-rw-r--r--  1 root root 81270 4月  13 20:18 modules.builtin.modinfo

-rw-r--r--  1 root root  7568 4月  14 08:51 modules.dep

-rw-r--r--  1 root root 11475 4月  14 08:51 modules.dep.bin

-rw-r--r--  1 root root   126 4月  14 08:51 modules.devname

-rw-r--r--  1 root root  2983 4月  13 20:18 modules.order

-rw-r--r--  1 root root    85 4月  14 08:51 modules.softdep

-rw-r--r--  1 root root 71730 4月  14 08:51 modules.symbols

-rw-r--r--  1 root root 81094 4月  14 08:51 modules.symbols.bin

lrwxrwxrwx  1 root root    34 4月  13 20:18 source -> /home/sunlion/Desktop/linux-5.17.2

 

符號連接buildsource 指向的是源碼文件的安裝目錄,后面編寫驅動需要提供給makefile,而且需要是編譯配置過之后的源碼,“純”代碼,.config文件都沒有,是不行的。所以用於編譯的源碼放在一個合適的位置比較重要(例如 /usr/src/),這里放在桌面就比較隨意了。最好是專門做一個環境變量來標志源碼目錄。

 

安裝內核

$sudo make install          #安裝內核

執行后,輸出如下:

arch/x86/Makefile:154: CONFIG_X86_X32 enabled but no binutils support

sh ./arch/x86/boot/install.sh 5.17.2 \

arch/x86/boot/bzImage System.map "/boot"

run-parts: executing /etc/kernel/postinst.d/apt-auto-removal 5.17.2 /boot/vmlinuz-5.17.2

run-parts: executing /etc/kernel/postinst.d/initramfs-tools 5.17.2 /boot/vmlinuz-5.17.2

update-initramfs: Generating /boot/initrd.img-5.17.2

run-parts: executing /etc/kernel/postinst.d/unattended-upgrades 5.17.2 /boot/vmlinuz-5.17.2

run-parts: executing /etc/kernel/postinst.d/update-notifier 5.17.2 /boot/vmlinuz-5.17.2

run-parts: executing /etc/kernel/postinst.d/vboxadd 5.17.2 /boot/vmlinuz-5.17.2

VirtualBox Guest Additions: Building the modules for kernel 5.17.2.

 

VirtualBox Guest Additions: Look at /var/log/vboxadd-setup.log to find out what

went wrong

run-parts: executing /etc/kernel/postinst.d/xx-update-initrd-links 5.17.2 /boot/vmlinuz-5.17.2

I: /boot/initrd.img.old is now a symlink to initrd.img-5.13.0-39-generic

I: /boot/initrd.img is now a symlink to initrd.img-5.17.2

run-parts: executing /etc/kernel/postinst.d/zz-update-grub 5.17.2 /boot/vmlinuz-5.17.2

Sourcing file `/etc/default/grub'

Sourcing file `/etc/default/grub.d/init-select.cfg'

Generating grub configuration file ...

Found linux image: /boot/vmlinuz-5.17.2

Found initrd image: /boot/initrd.img-5.17.2

Found linux image: /boot/vmlinuz-5.13.0-39-generic

Found initrd image: /boot/initrd.img-5.13.0-39-generic

Found linux image: /boot/vmlinuz-5.11.0-27-generic

Found initrd image: /boot/initrd.img-5.11.0-27-generic

Found memtest86+ image: /boot/memtest86+.elf

Found memtest86+ image: /boot/memtest86+.bin

done

這段輸出說明了make install完成的工作:

1.復制bzImage System.map文件到 "/boot"目錄;

2.生成initramfs文件到/boot/initrd.img-5.17.2;

3.更改grub的配置文件,把新內核的相關信息添加到配置中。

 

重啟,自動使用最新的內核,uname -a 可查看內核信息。(啟動時,按住shift可進入grub的選擇菜單,選擇一個內核)

2.6總結

$ sudo apt update

$ sudo apt install git fakeroot build-essential ncurses-dev xz-utils libssl-dev bc flex libelf-dev bison dwarves zstd

$ make distclean

$ lsmod > /tmp/lsmod.now

$ make LSMOD=/tmp/lsmod.now localmodconfig

$ scripts/config --disable SYSTEM_TRUSTED_KEYS

$ scripts/config --disable SYSTEM_REVOCATION_KEYS

$ make menuconfig

$ make -j4            #使用4線程編譯

$ sudo make modules_install  #安裝模塊

$ sudo make install          #安裝內核

  

其他一些可能有用的menuconfig配置

Kernel .config support:將.config配置信息保存在內核中,選上它及它的子項使得其它用戶能從為文件/proc/config.gz 中得到內核的配置。

 

 

參考:

 

https://blog.csdn.net/u013014440/article/details/44154947

Linux內核程序開發

 


免責聲明!

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



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