通過創建一個最小的根文件系統,并使用QEMU和GDB進行調試。
1.準備工作環境
確保系統上安裝了所有必要的工具和依賴項。
sudo apt-get update //更新一下軟件包
sudo apt-get install build-essential git libncurses-dev bison flex libssl-dev qemu-system-x86 gdb busybox-static
-
sudo apt-get install build-essential:安裝編譯工具鏈,其中包含了gcc(GNU編譯器集合,用于C/C++程序)、g++(GNU C++編譯器)、make(構建工具,用于自動化編譯和安裝)、libc-dev(C標準庫的開發文件)。
- git:分布式版本控制系統。
- libncurses-dev:提供字符終端處理庫的開發文件。在編譯和配置內核的時候,需要依賴此庫。
- bison:GNU解析器生成器。用于生成語法分析器(Parser),在編譯內核時可能會使用。
- flex:快速詞法分析器生成器。配合bison使用。
- libssl-dev:解密一些協議,在內核模塊可能使用。
- qemu-system-x86:QEMU的x86系統模擬器。用于模擬x86架構的虛擬機,支持運行操作系統內核或完整系統。
- gdb:GNU調試器。用于調試C/C++程序,支持設置斷點、單步執行、查看變量和內存,與QEMU配合使用,調試Linux內核。
- busybox-static:靜態編譯的BusyBox工具集,提供一組精簡的Unix工具,將所有依賴庫都包含在可執行文件中,無需外部依賴。
2.獲取并配置Linux內核源碼
先進入到一個目錄下,然后自己克隆就可以了
git clone https://github.com/torvalds/linux.git
cd linux
3.配置內核
為了簡化過程,可以使用默認配置并啟動調試信息:
make defconfig
在Linux源代碼中,找到 .config 文件,然后“Ctrl + f”啟動搜索鍵,搜索調試信息“CONFIG_DEBUG_INFO”,然后可能會出現“CONFIG_DEBUG_INFO_NODE”,你就把他注釋了。然后你進行編譯“make -j4”,啟動四個內核進行編譯,提高速度,但是會出現四個調試選項,是因為你把之前個給注釋了,在這里你要選擇與“CONFIG_DEBUG_INFO”相關的。之后就會成功編譯。
編譯成功后,你應該能找到兩個文件:
- arch/x86/boot/bzImage:這是內核映像文件。
- vmlinux:這是未壓縮的內核映像文件,用于GDB調試。
4.創建最小的根文件系統
4.1準備目錄結構
創建一個目錄來存放根文件系統的文件:
mkdir -p ~/Compiler-2/rootfs //具體路徑視情況而定
cd ~/Compiler-2/rootfs
mkdir -p bin sbin etc proc sys usr/bin usr/sbin
ln -s bin sbin
- bin:存放系統的基本指令(二進制可執行文件),這些命令對所有用戶可用。
- sbin:存放系統管理員使用的管理命令(二進制可執行文件),通常需要root權限才能執行。
- etc:存放系統的配置文件,包括一些用戶信息,網絡配置等
- proc:一個虛擬文件系統,提供內核和進程信息的接口。它不占用磁盤空間,而是由內核動態生成。包括CPU信息、內存信息等
- sys:一個虛擬文件系統,提供內核和硬件設備的配置接口。與proc類似,它也是由內核動態生成的。用來配置內核參數、管理設備等
- usr/bin:存放用戶安裝的命令和應用程序(二進制可執行文件)。gcc、vim等
- usr/sbin:存放用戶安裝的系統管理命令(二進制可執行文件),通常需要root權限才能執行、
第三行創建的很多目錄是Linux文件系統層次結構標準(FHS)的一部分。
第四行命令的作用是創建一個 符號鏈接(symbolic link),將sbin目錄軟鏈接到bin目錄。因為在某些情況下,bin和sbin目錄的內容可能會相同或相似,通過將sbin鏈接到bin,可以節省空間,方便統一管理,之后也就不需要區分這兩個目錄,也可以簡化路徑。
4.2復制BuysBox二進制文件
復制BusyBox二進制文件到根文件系統目錄:
cp $(which busybox) bin/
將當前目錄下 bin/ 目錄中的 busybox 可執行文件所支持的所有工具,以符號鏈接的形式安裝到指定目錄中(其實就是默認當前目錄下的 bin/ 目錄)。其中-s是 --install 選項的子選項,表示創建符號鏈接而不是硬鏈接(hard link)。
./bin/busybox --install -s
4.3創建 init 腳本
在根文件系統中創建一個簡單的初始化腳本(init script)來啟動shell:
創建一個名為 init 的文件,并將 #!/bin/sh 寫入文件的第一行。其中?#!/bin/sh 是腳本的 shenbang,指定腳本使用 /bin/sh(Bourne Shell)作為解釋器。
echo '#!/bin/sh' > init
將?mount -t proc none /proc 追加到 init 文件中。mount -t proc none /proc 掛載 proc 文件系統打破 /proc 目錄。proc文件系統提供了內核和進程信息的接口,是Linux系統的重要組成部分。>> init將輸出追加到init文件中,不會覆蓋原有內容。
echo 'mount -t proc none /proc' >> init
sysfs文件系統提供了內核和硬件設備的配置接口,通常用于管理設備和內核模塊。
echo 'mount -t sysfs none /sys' >> init
exec sh 是啟動一個交互式的Shell。exec 用新的進程替換當前進程。這行代碼的作用是讓系統在初始化完成后進入一個交互式的 Shell 環境,方便用戶操作或調試。
echo 'exec sh' >> init
為 init 文件添加可執行權限。這行代碼的作用是讓 init 文件可以被執行。因為在Linux系統中,腳本文件必須具有可執行權限才能直接運行。
chmod +x init
4.4 打包成 cpio 歸檔
將 rootfs 目錄打包成一個 cpio 歸檔文件,并使用 gzip 壓縮,最終生成一個壓縮的根文件系統映像文件 rootfs.cpio.gz。
cd ~/Compiler-2
find rootfs | cpio -o --format=newc | gzip > rootfs.cpio.gz
最后在我的電腦上,輸出 1 block,表示 cpio 歸檔文件中只包含一個塊的數據(512字節)。
5.使用QEMU啟動內核
在第一個終端窗口中運行一下命令啟動QEMU:
qemu-system-x86_64 \-kernel arch/x86/boot/bzImage \-append nokaslr\-s -S \-m 2024
- qemu-system-x86_64:這是QEMU的可執行文件,用于模擬x86_64架構的虛擬機
- -kernel linux/arch/x86/boot/bzImage:指定要啟動的Linux內核鏡像文件(在上面編譯的時候也提到了)
- -s:啟用 GDB 調試服務器,默認監聽端口 1234
- -S:啟動時暫停CPU,等待GDB連接。
- -m 2024 :給虛擬機分配2024MB? ?//可加可不加
6.啟動GDB連接QEMU進行調試
在第二個終端窗口中啟動GDB并連接到QEMU:
cd ~/Compiler-2/linux-6.1
gdb vmlinux
(gdb) target remote localhost:1234
(gdb) continue
之后你就可以使用gdb打斷點進行調試了。(*^▽^*)