在Ubuntu上編譯安裝linux核心詳細過程
在Ubuntu上編譯安裝linux核心詳細過程
時間:20220414,版本:V0.1
作者:robotech_erx
1.預備
1.1解釋題目
一個linux系統需要3個元件:核心、根檔案系統、bootloader。不管是哪個發行版或者嵌入式系統,核心都是一樣的。Bootloader也相對簡單,pc上用grub,嵌入式系統上用uboot。比較麻煩的是構建根檔案系統(init系統,GUI,編譯工具,shell,各種工具等等)。嵌入式系統上還好說,有很多的工具可以快速的搞出一個最小(或者不那麼小的)根檔案系統。PC上的根檔案系統,工作量就很龐大了,不是那麼快能完成的。其實一個發行版,比如ubuntu
因此,這裡僅僅是編譯一個新的核心並安裝,修改一下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:次版本號,一個次版本號出現通常代表著是一個穩定版本
0:patchlevel,applied on occasion to the stable kernel when significant bug/security fixes are required.
-39-generic:EXTRAVERSION,又稱作localversion,通常是發行版使用,用於標記發行版對核心的修改。
1.3發行版本和核心版本的對應關係
從版本號可以知道(-39-generic),發行版的核心與原版相比是有修改的。下載發行版的程式碼可以參考:
https://wiki.ubuntu.com/Kernel/Dev/KernelGitGuide
https://cloud.tencent.com/developer/article/1439068 找到執行的Ubuntu版本對應的核心原始碼
我們這裡使用原始版本的程式碼編譯一個核心,但是檔案系統使用的還是ubuntu20.04的。Ubuntu
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,比較大的檔案(900多M,bzImage 不到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
符號連線build和source 指向的是原始碼檔案的安裝目錄,後面編寫驅動需要提供給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核心程式開發