建定制Linux內(nèi)核與系統(tǒng)鏡像:嵌入式開發(fā)與系統(tǒng)裁剪實(shí)戰(zhàn))
1. 項(xiàng)目概述與核心價(jià)值最近在折騰一個(gè)嵌入式項(xiàng)目需要為一塊特定的開發(fā)板定制一個(gè)輕量級(jí)的Linux系統(tǒng)。官方的Ubuntu Server鏡像雖然方便但內(nèi)核版本固定驅(qū)動(dòng)支持不全還帶了一堆我用不上的服務(wù)和軟件包占用了寶貴的存儲(chǔ)空間和內(nèi)存。于是我決定從最底層開始自己動(dòng)手編譯一個(gè)精簡的Linux內(nèi)核并以此為基礎(chǔ)制作一個(gè)完全貼合我需求的系統(tǒng)鏡像。這個(gè)過程說白了就是“內(nèi)核編譯”加“鏡像制作”兩件大事。對(duì)于很多從應(yīng)用層開發(fā)轉(zhuǎn)向底層系統(tǒng)或者從事嵌入式、IoT、云計(jì)算基礎(chǔ)設(shè)施工作的朋友來說掌握這套流程是進(jìn)階的必經(jīng)之路。它不僅能讓你徹底理解一個(gè)Linux系統(tǒng)是如何從源代碼“生長”出來的更能讓你獲得對(duì)系統(tǒng)的絕對(duì)控制權(quán)你可以裁剪掉所有冗余功能只保留必需的驅(qū)動(dòng)和子系統(tǒng)讓系統(tǒng)跑得更快、更省資源你可以打上最新的安全補(bǔ)丁或者集成還未被主流發(fā)行版收錄的硬件驅(qū)動(dòng)你甚至可以為特定的應(yīng)用場(chǎng)景比如高實(shí)時(shí)性、高安全性調(diào)整內(nèi)核的成百上千個(gè)配置參數(shù)。自己編譯內(nèi)核并制作鏡像就像是為你的硬件和應(yīng)用量身定制一套最合身的“操作系統(tǒng)西裝”而不是去商場(chǎng)買一件可能袖子長、腰身松的成衣。接下來我將以Ubuntu 22.04 LTS作為編譯環(huán)境詳細(xì)拆解從獲取內(nèi)核源碼、配置、編譯到創(chuàng)建根文件系統(tǒng)、打包成可啟動(dòng)鏡像的全過程。我會(huì)重點(diǎn)分享我在這個(gè)過程中踩過的坑和總結(jié)出的實(shí)用技巧目標(biāo)是讓你看完后能獨(dú)立完成一次完整的內(nèi)核定制與鏡像構(gòu)建。2. 編譯環(huán)境準(zhǔn)備與內(nèi)核源碼獲取工欲善其事必先利其器。編譯內(nèi)核是個(gè)資源消耗型任務(wù)尤其是鏈接階段對(duì)內(nèi)存和CPU要求較高。一個(gè)穩(wěn)定、純凈的編譯環(huán)境能避免很多稀奇古怪的問題。2.1 基礎(chǔ)編譯環(huán)境搭建我選擇在一臺(tái)物理機(jī)上的Ubuntu 22.04 LTS中進(jìn)行操作當(dāng)然在配置足夠的虛擬機(jī)中也可以。首先我們需要安裝所有必要的開發(fā)工具和庫文件。打開終端執(zhí)行以下命令來更新軟件包列表并安裝基礎(chǔ)編譯工具鏈sudo apt update sudo apt upgrade -y sudo apt install -y build-essential libncurses-dev libssl-dev bc \ flex bison libelf-dev dwarves zstd cpio git這里解釋一下幾個(gè)關(guān)鍵包的作用build-essential: 提供了gcc,g,make等最核心的編譯工具。libncurses-dev: 用于支持make menuconfig這種文本圖形化配置界面沒有它你就只能面對(duì)純文本配置文件或者用make xconfig需要圖形界面。libssl-devbc: 內(nèi)核配置和編譯過程中某些環(huán)節(jié)如生成證書會(huì)用到。flexbison: 語法分析器生成器編譯內(nèi)核時(shí)需要。libelf-dev: 處理ELF可執(zhí)行與可鏈接格式文件所需的庫對(duì)現(xiàn)代內(nèi)核構(gòu)建至關(guān)重要。dwarves: 包含pahole工具用于優(yōu)化內(nèi)核數(shù)據(jù)結(jié)構(gòu)布局對(duì)生成更高效的內(nèi)核有幫助。zstd: 一種高效的壓縮算法內(nèi)核鏡像壓縮可能會(huì)用到。注意如果你的Ubuntu版本較新或較舊某些包名可能有細(xì)微差別。安裝完成后可以用gcc --version和make --version驗(yàn)證工具鏈?zhǔn)欠窬途w。2.2 獲取內(nèi)核源碼獲取內(nèi)核源碼主要有兩種途徑一是從Linux內(nèi)核官方倉庫下載二是使用你的發(fā)行版如Ubuntu提供的內(nèi)核源碼包。方案一從 kernel.org 獲取推薦用于深度定制這是最直接、最上游的方式。你可以訪問 https://www.kernel.org/ 查看最新穩(wěn)定版stable或長期支持版longterm。使用wget下載例如下載6.6版本cd ~ wget https://cdn.kernel.org/pub/linux/kernel/v6.x/linux-6.6.tar.xz tar -xvf linux-6.6.tar.xz cd linux-6.6方案二使用Ubuntu提供的內(nèi)核源碼這種方式獲取的內(nèi)核已經(jīng)包含了Ubuntu特定的補(bǔ)丁和配置如果你只是想基于當(dāng)前系統(tǒng)內(nèi)核進(jìn)行微調(diào)這可能更方便。sudo apt install linux-source-$(uname -r)安裝后源碼包通常是tar.xz格式會(huì)放在/usr/src/目錄下需要解壓。我個(gè)人更傾向于方案一因?yàn)樗姹厩逦鷽]有額外的補(bǔ)丁干擾更適合學(xué)習(xí)原理和進(jìn)行干凈的定制。本次演示我們就使用從kernel.org下載的6.6版本源碼。實(shí)操心得在解壓源碼的目錄外單獨(dú)建立一個(gè)編譯輸出目錄build是很好的實(shí)踐可以將源碼樹和編譯生成的文件分離保持源碼目錄的整潔也方便進(jìn)行多種配置的編譯。我們可以這樣操作mkdir -p ~/kernel_build cd ~/linux-6.6 # 后續(xù)的編譯輸出將指向 ~/kernel_build 目錄3. 內(nèi)核配置定制的藝術(shù)這是整個(gè)過程中最核心、最考驗(yàn)經(jīng)驗(yàn)的一步。內(nèi)核有上萬個(gè)配置選項(xiàng)決定了最終內(nèi)核支持什么硬件、包含什么功能、性能如何。3.1 配置界面與基礎(chǔ)方法進(jìn)入內(nèi)核源碼目錄我們有幾種配置方式make defconfig: 生成一個(gè)基于當(dāng)前架構(gòu)x86_64的默認(rèn)配置。這是起點(diǎn)。make olddefconfig: 在已有.config文件基礎(chǔ)上用新內(nèi)核版本的默認(rèn)值來更新并自動(dòng)解決新出現(xiàn)的選項(xiàng)。從舊配置升級(jí)時(shí)常用。make menuconfig: 基于ncurses的文本圖形化界面最常用不需要完整的圖形桌面環(huán)境。make xconfig: 基于Qt的圖形化配置界面更直觀但需要安裝Qt庫和圖形界面。make gconfig: 基于GTK的圖形化配置界面。對(duì)于服務(wù)器環(huán)境make menuconfig是首選。我們先生成一個(gè)默認(rèn)配置然后進(jìn)入定制界面cd ~/linux-6.6 make O~/kernel_build defconfig # 使用O指定輸出目錄 make O~/kernel_build menuconfig執(zhí)行menuconfig后你會(huì)看到一個(gè)分層級(jí)的菜單界面。使用方向鍵導(dǎo)航空格鍵選擇[*]表示編譯進(jìn)內(nèi)核[M]表示編譯為模塊[ ]表示不編譯/鍵可以搜索配置項(xiàng)?鍵查看幫助。3.2 關(guān)鍵配置項(xiàng)解析與裁剪策略面對(duì)海量選項(xiàng)新手容易無從下手。我的策略是先繼承后裁剪再特化。繼承現(xiàn)有配置一個(gè)非常高效的方法是使用當(dāng)前運(yùn)行系統(tǒng)的配置作為起點(diǎn)。這能最大程度保證新內(nèi)核能驅(qū)動(dòng)你現(xiàn)有的硬件。cp /boot/config-$(uname -r) ~/kernel_build/.config make O~/kernel_build olddefconfig這條命令復(fù)制當(dāng)前系統(tǒng)的配置并用新內(nèi)核的默認(rèn)值填充新增的選項(xiàng)。核心裁剪方向文件系統(tǒng)如果你只為特定設(shè)備制作鏡像可以只保留它需要的文件系統(tǒng)。例如只用于SD卡或eMMC的嵌入式設(shè)備可以主要保留ext4去掉btrfs,xfs,ntfs等。在File systems菜單下操作。設(shè)備驅(qū)動(dòng)這是裁剪的大頭。在Device Drivers菜單下你可以根據(jù)目標(biāo)硬件移除所有不相關(guān)的驅(qū)動(dòng)。比如你的目標(biāo)設(shè)備是ARM架構(gòu)的嵌入式板沒有USB攝像頭、沒有特定的PCIe網(wǎng)卡就可以大膽移除。但要小心一些基礎(chǔ)驅(qū)動(dòng)如ATA/ATAPI/MFM/RLL support,SCSI device support即使你用不到SCSI但很多子系統(tǒng)依賴它可能需要保留。網(wǎng)絡(luò)支持如果設(shè)備不需要網(wǎng)絡(luò)可以在Networking support中徹底禁用。如果需要?jiǎng)t只啟用必要的協(xié)議如TCP/IP和網(wǎng)絡(luò)設(shè)備驅(qū)動(dòng)如具體的網(wǎng)卡型號(hào)。調(diào)試與性能分析Kernel hacking下的很多調(diào)試選項(xiàng)會(huì)顯著增大內(nèi)核體積并影響性能在生成最終產(chǎn)品鏡像時(shí)應(yīng)關(guān)閉。內(nèi)核壓縮模式在General setup-Kernel compression mode中可以選擇壓縮算法。zstd壓縮率好且解壓速度快是比較現(xiàn)代的選擇。一個(gè)重要的技巧使用localmodconfig如果你是為當(dāng)前編譯的這臺(tái)機(jī)器定制內(nèi)核有一個(gè)神器make O~/kernel_build localmodconfig這個(gè)命令會(huì)分析當(dāng)前系統(tǒng)加載了哪些內(nèi)核模塊lsmod的輸出然后修改.config文件只將當(dāng)前正在使用的驅(qū)動(dòng)和功能編譯進(jìn)內(nèi)核或模塊其他的全部禁用。這能生成一個(gè)非常精簡的配置。執(zhí)行后記得再運(yùn)行make olddefconfig處理一下依賴。踩坑記錄曾經(jīng)有一次我裁剪得太激進(jìn)把CONFIG_BLK_DEV_INITRD初始RAM磁盤支持給關(guān)掉了。結(jié)果內(nèi)核無法加載initramfs導(dǎo)致系統(tǒng)啟動(dòng)失敗。對(duì)于通用系統(tǒng)一些看似無關(guān)的基礎(chǔ)功能如initramfs支持、EFI支持、/dev和/proc文件系統(tǒng)支持一定要確認(rèn)是否需要。配置完成后保存退出。配置文件會(huì)保存在~/kernel_build/.config。強(qiáng)烈建議備份這個(gè)文件。4. 內(nèi)核編譯與安裝配置搞定接下來就是相對(duì)自動(dòng)化的編譯過程了。4.1 啟動(dòng)編譯過程使用make命令進(jìn)行編譯。為了充分利用多核CPU加速編譯可以加上-j參數(shù)指定并行任務(wù)數(shù)。通常設(shè)置為CPU核心數(shù) 1或CPU核心數(shù) * 2。你可以用nproc命令查看核心數(shù)。cd ~/linux-6.6 make O~/kernel_build -j$(($(nproc)1))這個(gè)過程視硬件性能而定可能需要十幾分鐘到一小時(shí)以上。你會(huì)看到大量的編譯信息滾動(dòng)。如果中途出現(xiàn)錯(cuò)誤通常是缺少某個(gè)依賴庫根據(jù)錯(cuò)誤信息安裝對(duì)應(yīng)的-dev包即可。4.2 安裝編譯產(chǎn)物編譯成功后我們需要安裝內(nèi)核模塊和內(nèi)核鏡像文件。安裝模塊模塊會(huì)被安裝到指定的目錄我們通常將其安裝到一個(gè)臨時(shí)目錄以便后續(xù)打包進(jìn)根文件系統(tǒng)。sudo make O~/kernel_build modules_install INSTALL_MOD_PATH~/rootfs這里INSTALL_MOD_PATH~/rootfs指定了安裝路徑~/rootfs是我們接下來要構(gòu)建的根文件系統(tǒng)目錄。如果不指定默認(rèn)會(huì)安裝到宿主系統(tǒng)的/lib/modules下這可能會(huì)干擾現(xiàn)有系統(tǒng)。準(zhǔn)備內(nèi)核鏡像編譯生成的核心文件是vmlinuz壓縮的內(nèi)核映像和System.map內(nèi)核符號(hào)表。我們將其復(fù)制出來。cp ~/kernel_build/arch/x86/boot/bzImage ~/my_custom_kernel/vmlinuz-6.6.0-custom cp ~/kernel_build/System.map ~/my_custom_kernel/ cp ~/kernel_build/.config ~/my_custom_kernel/config-6.6.0-custom注意如果你是ARM等其它架構(gòu)bzImage的路徑會(huì)是arch/arm/boot/zImage等。至此內(nèi)核部分的工作就完成了。我們得到了一個(gè)定制化的內(nèi)核文件vmlinuz-6.6.0-custom和對(duì)應(yīng)的模塊位于~/rootfs/lib/modules/下。5. 構(gòu)建根文件系統(tǒng)內(nèi)核負(fù)責(zé)管理硬件和進(jìn)程但一個(gè)可用的系統(tǒng)還需要用戶空間userspace的程序比如基本的shell、工具集ls,cp,mkdir等、初始化系統(tǒng)。這些就構(gòu)成了根文件系統(tǒng)rootfs。5.1 使用debootstrap構(gòu)建最小Ubuntu根文件系統(tǒng)對(duì)于基于Debian/Ubuntu的環(huán)境debootstrap是構(gòu)建根文件系統(tǒng)的標(biāo)準(zhǔn)工具。它可以安裝一個(gè)最小的Ubuntu系統(tǒng)到指定目錄。sudo apt install debootstrap sudo mkdir -p ~/rootfs sudo debootstrap --archamd64 jammy ~/rootfs http://archive.ubuntu.com/ubuntu/--archamd64: 指定架構(gòu)。jammy: Ubuntu 22.04的代號(hào)。~/rootfs: 目標(biāo)目錄。http://archive.ubuntu.com/ubuntu/: 軟件源地址。這個(gè)過程會(huì)下載并安裝最基礎(chǔ)的包。完成后~/rootfs目錄下就是一個(gè)干凈的Ubuntu最小系統(tǒng)。5.2 基礎(chǔ)系統(tǒng)配置與必要軟件安裝現(xiàn)在我們需要chroot進(jìn)入這個(gè)新系統(tǒng)進(jìn)行一些配置。# 掛載必要的虛擬文件系統(tǒng) sudo mount --bind /dev ~/rootfs/dev sudo mount --bind /dev/pts ~/rootfs/dev/pts sudo mount -t proc proc ~/rootfs/proc sudo mount -t sysfs sysfs ~/rootfs/sys # 使用chroot進(jìn)入新環(huán)境 sudo chroot ~/rootfs /bin/bash現(xiàn)在你的終端環(huán)境已經(jīng)切換到了新的根文件系統(tǒng)內(nèi)。設(shè)置基礎(chǔ)信息# 設(shè)置主機(jī)名 echo my-custom-ubuntu /etc/hostname # 設(shè)置root密碼 passwd # 配置軟件源可選保持默認(rèn)也可 # cat /etc/apt/sources.list EOF # deb http://archive.ubuntu.com/ubuntu/ jammy main restricted universe multiverse # deb http://archive.ubuntu.com/ubuntu/ jammy-updates main restricted universe multiverse # deb http://archive.ubuntu.com/ubuntu/ jammy-security main restricted universe multiverse # EOF apt update安裝必要軟件根據(jù)你的需求安裝。至少需要apt install -y systemd-sysv udev sudo net-tools iproute2 iputils-ping vimsystemd-sysv: 提供systemd并替換sysvinit。udev: 動(dòng)態(tài)設(shè)備管理。sudo: 權(quán)限管理。網(wǎng)絡(luò)工具用于調(diào)試。創(chuàng)建普通用戶可選但推薦adduser myuser usermod -aG sudo myuser配置網(wǎng)絡(luò)最簡單的配置是使用DHCP。cat /etc/netplan/01-netcfg.yaml EOF network: version: 2 renderer: networkd ethernets: eth0: dhcp4: yes EOF配置串口終端對(duì)于無顯示器的嵌入式設(shè)備很重要編輯/etc/systemd/system/getty.target.wants/gettytty1.service但更簡單的方法是創(chuàng)建一個(gè)systemd的覆蓋或直接修改inittab的替代品。對(duì)于使用systemd的系統(tǒng)可以啟用串口gettysystemctl enable serial-gettyttyS0.service # 將ttyS0替換為你的實(shí)際串口設(shè)備如ttyAMA0樹莓派退出chroot并卸載exit # 退出chroot環(huán)境 sudo umount ~/rootfs/dev/pts sudo umount ~/rootfs/dev sudo umount ~/rootfs/proc sudo umount ~/rootfs/sys5.3 整合自定義內(nèi)核模塊還記得我們之前把模塊安裝到~/rootfs了嗎現(xiàn)在它們已經(jīng)在正確的位置了~/rootfs/lib/modules/6.6.0-custom/。你需要確保模塊的依賴關(guān)系正確生成# 回到宿主環(huán)境在rootfs目錄外操作 sudo chroot ~/rootfs depmod -a 6.6.0-custom6. 制作可啟動(dòng)磁盤鏡像現(xiàn)在我們有內(nèi)核vmlinuz和根文件系統(tǒng)rootfs需要把它們打包成一個(gè)硬盤鏡像文件如img或qcow2這個(gè)鏡像可以被虛擬機(jī)直接啟動(dòng)或者寫入到物理SD卡、硬盤中。6.1 創(chuàng)建空白鏡像并分區(qū)我們將創(chuàng)建一個(gè)1GB大小的RAW格式鏡像并分成兩個(gè)區(qū)一個(gè)小的boot分區(qū)存放內(nèi)核和一個(gè)大的root分區(qū)存放根文件系統(tǒng)。cd ~ dd if/dev/zero ofmy-ubuntu.img bs1M count1024 # 創(chuàng)建1GB空白文件 sudo parted my-ubuntu.img --script mklabel msdos # 創(chuàng)建MBR分區(qū)表 sudo parted my-ubuntu.img --script mkpart primary fat32 1MiB 256MiB # 創(chuàng)建256M的FAT32 boot分區(qū) sudo parted my-ubuntu.img --script mkpart primary ext4 256MiB 100% # 剩余空間創(chuàng)建ext4根分區(qū)6.2 掛載鏡像并格式化分區(qū)我們需要使用loop設(shè)備將鏡像文件虛擬成塊設(shè)備然后對(duì)分區(qū)進(jìn)行格式化。# 查找可用的loop設(shè)備并關(guān)聯(lián)鏡像文件 LOOP_DEV$(sudo losetup --show -f -P my-ubuntu.img) echo $LOOP_DEV # 會(huì)輸出類似 /dev/loop0 # 格式化分區(qū) sudo mkfs.vfat -F 32 ${LOOP_DEV}p1 # 格式化boot分區(qū)為FAT32 sudo mkfs.ext4 ${LOOP_DEV}p2 # 格式化root分區(qū)為ext4 # 創(chuàng)建掛載點(diǎn)并掛載 mkdir -p mnt/{boot,root} sudo mount ${LOOP_DEV}p1 mnt/boot sudo mount ${LOOP_DEV}p2 mnt/root6.3 復(fù)制文件系統(tǒng)與內(nèi)核復(fù)制根文件系統(tǒng)使用rsync或cp復(fù)制rsync能更好地保留權(quán)限和屬性。sudo rsync -a ~/rootfs/ mnt/root/安裝內(nèi)核與引導(dǎo)程序復(fù)制內(nèi)核到boot分區(qū)sudo cp ~/my_custom_kernel/vmlinuz-6.6.0-custom mnt/boot/vmlinuz安裝引導(dǎo)程序這里以extlinux為例它比GRUB更輕量sudo apt install extlinux sudo extlinux --install mnt/boot/創(chuàng)建extlinux配置文件sudo tee mnt/boot/extlinux.conf EOF DEFAULT linux LABEL linux SAY Booting My Custom Ubuntu... KERNEL /vmlinuz APPEND root/dev/sda2 rw quiet splash # 注意root/dev/sda2 指定了根分區(qū)。在虛擬機(jī)或?qū)嶋H設(shè)備中這個(gè)設(shè)備名可能會(huì)變?nèi)?dev/mmcblk0p2。 # 更穩(wěn)妥的做法是使用UUID或PARTUUID。 EOF獲取root分區(qū)的UUIDsudo blkid ${LOOP_DEV}p2然后將root/dev/sda2替換為rootUUIDxxxx-xxxx。6.4 收尾工作# 同步數(shù)據(jù)并卸載 sync sudo umount mnt/boot sudo umount mnt/root sudo losetup -d $LOOP_DEV # 解除loop設(shè)備關(guān)聯(lián) # 清理掛載點(diǎn) rm -rf mnt現(xiàn)在my-ubuntu.img就是一個(gè)包含了你的自定義內(nèi)核和根文件系統(tǒng)的可啟動(dòng)磁盤鏡像了。你可以用qemu虛擬機(jī)測(cè)試它qemu-system-x86_64 -drive filemy-ubuntu.img,formatraw -m 10247. 常見問題與排查技巧實(shí)錄在整個(gè)過程中你可能會(huì)遇到各種問題。這里記錄幾個(gè)我遇到過的典型問題及解決方法。7.1 編譯階段錯(cuò)誤錯(cuò)誤fatal error: openssl/opensslv.h: No such file or directory原因缺少OpenSSL開發(fā)頭文件。解決安裝libssl-dev包。sudo apt install libssl-dev錯(cuò)誤recipe for target ‘scripts/mod/empty.o’ failed原因通常是因?yàn)閎c計(jì)算器工具未安裝或版本問題。解決確保已安裝bc。sudo apt install bc錯(cuò)誤No rule to make target ‘debian/canonical-certs.pem’原因這是Ubuntu內(nèi)核源碼特有的簽名問題。使用上游kernel.org源碼通常不會(huì)遇到。解決在.config中關(guān)閉CONFIG_SYSTEM_TRUSTED_KEYS和CONFIG_SYSTEM_REVOCATION_KEYS將其值設(shè)為空字符串。7.2 啟動(dòng)階段錯(cuò)誤現(xiàn)象內(nèi)核panic提示VFS: Unable to mount root fs on unknown-block(0,0)原因內(nèi)核找不到根文件系統(tǒng)。這是最常見的問題。排查檢查內(nèi)核配置確認(rèn)CONFIG_BLK_DEV_INITRD如果需要initramfs和對(duì)應(yīng)文件系統(tǒng)如CONFIG_EXT4_FSy已編譯進(jìn)內(nèi)核y而不是模塊m。檢查引導(dǎo)參數(shù)檢查extlinux.conf或grub.cfg中的root參數(shù)。設(shè)備名如/dev/sda2在虛擬機(jī)、物理機(jī)、不同控制器下會(huì)變化。強(qiáng)烈建議使用UUID。獲取UUIDsudo blkid /dev/sdX2(或你的分區(qū))。修改引導(dǎo)配置rootUUIDxxxx-xxxx檢查根文件系統(tǒng)完整性確保rootfs復(fù)制完整且必要的目錄/dev,/proc,/sys,/run在啟動(dòng)后能被正確掛載由systemd或init腳本完成?,F(xiàn)象啟動(dòng)后卡住無法進(jìn)入登錄提示符原因可能是初始化系統(tǒng)systemd或getty服務(wù)出現(xiàn)問題。排查在引導(dǎo)參數(shù)的root后面加上init/bin/bash例如root/dev/sda2 rw init/bin/bash。這會(huì)讓內(nèi)核直接啟動(dòng)bashshell而不是systemd。如果能進(jìn)入bash檢查/var/log/boot.log或journalctl的日志如果journal可用。檢查/etc/systemd/system/getty.target.wants/下的服務(wù)是否正常??梢試L試手動(dòng)啟動(dòng)/lib/systemd/systemd-getty tty1。7.3 鏡像相關(guān)與測(cè)試問題QEMU啟動(dòng)報(bào)錯(cuò)Could not read from CD-ROM (code 0003)原因QEMU默認(rèn)會(huì)嘗試從CD-ROM啟動(dòng)。解決在QEMU命令中顯式指定從硬盤啟動(dòng)并關(guān)閉CD-ROM-boot orderc -cdrom none制作的鏡像文件太大原因dd創(chuàng)建的鏡像文件是“稀疏文件”的相反它實(shí)實(shí)在在地寫入了1GB的零數(shù)據(jù)。優(yōu)化可以使用truncate創(chuàng)建稀疏文件或者編譯完成后用qemu-img convert轉(zhuǎn)換并壓縮為qcow2格式后者支持動(dòng)態(tài)分配空間更省磁盤。qemu-img convert -f raw -O qcow2 my-ubuntu.img my-ubuntu.qcow2使用qemu-img啟動(dòng)時(shí)指定-drive filemy-ubuntu.qcow2,formatqcow2。整個(gè)流程走下來雖然步驟繁多但每一步都有其明確的目的。從內(nèi)核配置的精細(xì)打磨到根文件系統(tǒng)的精心組裝再到鏡像的最終合成你獲得的不僅僅是一個(gè)可啟動(dòng)的鏡像更是對(duì)Linux系統(tǒng)從內(nèi)核到用戶空間的完整認(rèn)知。當(dāng)你第一次看到屏幕上滾動(dòng)著自己編譯的內(nèi)核的啟動(dòng)信息并成功登錄到自己構(gòu)建的系統(tǒng)時(shí)那種成就感是無可替代的。這為你后續(xù)進(jìn)行更深入的性能調(diào)優(yōu)、安全加固或嵌入式定制打下了堅(jiān)實(shí)的基礎(chǔ)。