Kernel Linux學習(一)——環境搭建
Kernel Linux學習——環境搭建
2020-08-0220:14:19 hawkJW
因為最近資訊保安競賽中經常出現Kernel Linux相關方面的習題,因此正好通過疫情這段時間學習一下Kernel Linux相關的知識。
這一此主要介紹Kernel Linux的環境的搭建。分別需要Linux的原始碼、Busybox的原始碼、以及qemu模擬器
總體分析
實際上,Linux的啟動首先一定需要核心程式——其通過Linux的原始碼進行下載,編譯即可。
除此之外,Linux的啟動還需要根檔案系統支援,因為當系統啟動時,僅僅只有核心程式,需要從磁碟中載入各種模組,而這個過程需要檔案系統;如果檔案系統放置在磁碟中,這就成為了一個雞生蛋、蛋生雞的問題。因此,即在RAM上建立臨時檔案系統,即根檔案系統,當所需模組載入完畢後再將根檔案系統轉移到磁碟上即可。這裡通過Busybox進行構建。
最後,如果在真機上直接進行執行,如果中間出現錯誤或者異常,則整個系統直接奔潰,對於執行或者除錯都不方便。因此,通過模擬器執行並除錯。
Linux核心
我們首先需要下載Linux核心原始碼,然後進行編譯即可,其原始碼的映象檔案如下連結所示https://mirrors.tuna.tsinghua.edu.cn/kernel/。我們進行下載即可,這裡我選擇了V4.x的4.4.72版本。
當然,安裝過程中可能會有一些依賴問題,我這裡一併包括qemu等更新安裝,程式碼如下所示
sudo apt-get install qemu build-essential libssl-dev kernel-package libncurses5-dev bison flex
這裡等待一段時間後,我們將下載的原始碼檔案進行解壓,並進入對應的目錄,程式碼如下所示
tar xf /path/to/linux-src.tar.gz rm -rf /path/to/linux-src.tar.gz mv /path/to/linux-src linux cd linux
然後我們需要進行編譯的配置,執行如下命令
make menuconfig
此時會進入編譯配置的gui介面,然後我們依次選擇如下的配置
——進入kernel hacking ——進入Compile-time checks and compiler options ——選擇Compile the kernel with debuginfo ——選擇Compile the kernel with frame pointers ——選中Kernel Debugging ——選中KGDB:Kernel Debugging ——關閉Write protect kernel read-only data structures
退出儲存後,執行如下命令
make -j 4
這樣子即完成了Kernel Linux的核心編譯部分。
根檔案系統編譯
下面我們將構建根檔案系統,我們這裡通過BusyBox來快速構建根檔案系統。我們首先進行busybox的編譯,其原始碼的映象連結如下圖所示https://busybox.net/downloads/,這裡我們選擇(1.27.2版本)。下載完後進行如下的命令
tar -xf /path/to/busybox-1.27.2.tar.bz2
rm -rf /path/to/busybox-1.27.2.tar.bz2
mv /path/to/busybox-1.27.2.tar.bz2 /path/to/busybox
下載並解壓完畢後,我們進行編譯的設定,命令如下所示
make defconfig make menuconfig
此時進入GUI介面後,我們選擇如下配置
進入Busybox Settings
——選擇Build BusyBox as a static binary(no shared libs)
退出儲存後,執行如下命令
make -j 4
make install
這樣子即完成了busybox的編譯工作。然後我們繼續構建根檔案系統。根據一些網路資料,根檔案系統至少需要包含所有支援完整Linux系統的結構和程式,目前至少需要
1. 基礎檔案系統結構 2. 必須的目錄——/dev、/bin、/etc等
3. 必須的程式——init等 4. 必須的配置檔案——inittab等 5. 必須的裝置檔案——/dev/console等 6. 配置檔案所需要的庫檔案
我們建立一個目錄,用來作為根檔案系統的目鱸形石,我們需要向目錄內部填充資料,下面我們需要向該目錄中寫入構建根檔案目錄的內容——/dev、/proc、/etc、/sbin、/bin、/lib、/sys、/mnt以及/usr檔案(有一些可以不用),其中,/proc、/mnt檔案僅僅需要建立即可,內容可以為空,其構建的命令如下所示
mkdir rootfs
cd rootfs
mkdir proc mkdir mnt
mkdir sys
mkdir tmp
對於/usr、/sbin以及/bin,直接將busybox編譯後的檔案全部賦值即可,命令如圖所示
cp -r ../busybox/_install/* ./
而/dev檔案包含所有裝置檔案,通過mknod命令建立裝置檔案。這裡我們建立console、null、tty1裝置檔案,可以在自己的Linux主機上通過如下命令進行檢視
ls -al /dev/
根據上面的結果,可以發現其命令如下圖所示
mkdir dev sudo mknod dev/console c 5 1 sudo mknod dev/null c 1 3 sudo mknod dev/tty1 c 4 1
/etc檔案中包含各種設定檔案,這裡我們構建inittab、init.d/rcS和fstab檔案。
其中inittab檔案指揮init進行進行工作,其內容如下
#/etc/inittab
::sysinit:/etc/init.d/rcS
::askfirst:-/bin/sh
::shutdown:/bin/umount -a -r
稍微分析一下該檔案的含義,所有的/etc/inittab每一行相當於一個指令碼,其內容類似於id:runlevel:action:precess
這裡第一行表示初始化時執行/etc/init.d/rcS檔案內容;第二行表按鍵後進入shell;第三行表示當關閉時umount所有掛載的檔案。
可以看到,其中第一句中執行了/etc/init.d/rcS檔案,則我們需要填充完善/etc/init.d/reS檔案,其內容如下所示
#!/bin/sh mount -a
注意需要給其可執行許可權。這裡面的內容很簡單,就是掛載所有的檔案系統,至於具體如何進行掛載,其按照/etc/fstab檔案中所描述的進行掛載,內容如下所示
proc /proc proc defaults 0 0
tmpfs /tmp tmpfs defaults 0 0
sysfs /sys sysfs defaults 0 0
tmpfs /dev tmpfs defaults 0 0
這裡我們需要詳細說明一下掛載這個概念。實際上如果你並沒有再fstab中寫這些規則,也就是並沒有進行如下的掛載,但是你仍然可以按照下面的流程進行核心的啟動,並且仍然可以在linux中看到這兩個目錄,如下圖所示
但是如果您進行了上述的掛載,然後再去觀察,結果如圖所示
實際上,根據這個實驗結果,並且配合上一些相關的網路資料,我們很容易就可以對於掛載這個概念有更深刻的瞭解。整個檔案系統實際上相當於這樣一個數據結構
union fileSystem{ memory data; union fileSystem *next; }
如果沒有進行掛載,則顯示其fileSystem.data中的資料;如果掛載了話,則顯示fileSystem.next中指向的資料。所以我們可以對上述現象進行合理解釋——首先正如上面分析的,一定會掛載根目錄,也就是這裡我們建立的這些目錄;如果沒有掛載,則顯示的就是目前資訊(空);如果進行了掛載,則顯示掛載的資訊。我們可以再做個實驗,如果我們在一開始的sys目錄下放一個README.md檔案,則如果不進行掛載的話,應該會顯示該檔案,結果如圖所示
這樣子,我們基本完成了目錄中的資料填充,然後我們將其打包為qemu可以直接使用的根目錄檔案格式,命令如下
find . | cpio -o --format=newc > ../rootfs.img
這樣子就完成了根檔案系統的製作
啟動核心
下面,我們即利用qemu,模擬Linux核心的啟動,我們需要制定一下linux核心、根檔案系統以及一些設定即可,-initrd後面跟的就是根檔案系統,命令如下
qemu-system-x86_64 -kernel linux/arch/x86_64/boot/bzImage -initrd rootfs.img -append "rdinit=/linuxrc"