開搞步驟
基於別人的 initrd 開始搞是很簡單的事。就像把大象放進冰箱裡一樣,思路很簡單,就四步:
- 下載 initrd
- 解壓 initrd
- 修改 initrd
- 打包 initrd
但都知道細節才是重點,本文將一步步解釋如何實現以上四點,以及其中的工具怎麼用
在繼續之前,不妨先弄一個目錄作為工作目錄,就叫 tinycore-linux-build
好了
本文將使用 x86_64 架構的 TinyCore 13 為例子。
下載
從 https://distro.ibiblio.org/tinycorelinux/13.x/x86_64/release/distribution_files/corepure64.gz
下載 initrd 即可。
解壓
注意,因為修改和打包 rootfs 涉及到塊設備、字符設備以及「權限保持」等問題,涉及到對 rootfs 的修改都需要使用 root 權限
新建一個目錄 rootfs
,然後
1 | # 在一個 subshell 內執行:進入目錄 rootfs,用 gzip 解壓 initrd 到管道喂進 cpio |
這裡用了括號把內容括起來,這樣語句就在 subshell 內執行,命令執行完畢對當前 shell 沒有影響。
命令內用到 gzip 和 cpio 命令,詳細講講這兩個命令以及參數
gzip 命令
- -d:解壓模式
- -c:輸出到 stdout,保留原檔案
cpio 命令
cpio 這裡用了聚合選項,-idm
是等價於 -i -d -m
的。
- -i:「輸入並解包」模式,從 stdin 讀取內容
- -d:按需創建目錄
- -m:保留修改時間不變
至此,就可以在 rootfs
得到 initrd 的內容了。
修改
rootfs
內的東西,就是 TinyCore 啟動時使用的數據,所以可以按需修改成自己想要的東西。
後面的章節會詳細講述部分檔案和配置。現在就先把解包和打包都做一遍先。
打包
修改完成後,執行:
1 | # 進入 rootfs,找出所有文件,並把列表喂給 cpio。將 subshell 的 |
這裡用到了 find 和 cpio 的另一個模式
find 命令
- -P:不進入鏈接,這是默認行為,可以不添加
- .:指定搜索當前目錄
cpio 命令
- -o:「打包並輸出」模式,從 stdin 讀取文件列表
- -H:指定打包格式,這裡使用 newc(The SVR4 portable cpio format.),可以用 –help 查看支持的模式
開始測試
開始測試之前,我們還得把內核搞到手,從 https://distro.ibiblio.org/tinycorelinux/13.x/x86_64/release/distribution_files/vmlinuz64
下載即可。
qemu 的使用
qemu 的使用有點複雜,需要參考一下 QEMU 的 Wiki 來敲命令,也可以打開 Arch Wiki 一起使用(效果更好)。
創建虛擬硬碟
雖然本例暫時不需要用到硬碟,但這裡也提及一下如何創建一個 qcow2 的硬碟:
1 | qemu-img create -f qcow2 disk01.qcow2 32G |
- create:創建指令
- -f:指定磁碟映像格式,這裡使用 qcow2
- disk01.qcow2:文件名
- 32G:大小,這裡是 32 GB。
qcow2 格式默認是按用量分配的,所以立即就能創建出來。
啟動
這裡先給出命令
1 | qemu-system-x86_64 \ |
qemu-system-x86_64
是創建 x86_64 虛擬機
- -m:指定內存,這裡給了 1GB
- -smp:指定核心數,這裡給了兩個核
- -machine:指定模擬的機器參數,這裡 type 選 q35,accel 是加速方式,我在 macOS 上所以選 hvf,linux 需用 kvm
- -netdev:創建一個網絡設備,用 user network 模式,給一個引用 id network0
- -vga:指定圖形驅動架構,這裡選 virtio
- -device:添加設備
- -display:指定輸出顯示方式,這裡用默認模式,顯示指針(就是會出來一個窗口作為虛擬機的顯示器)
- -kernel:指定 linux 內核檔,直接啟動
- -initrd:指定 linux 的 initrd 檔
- -append:傳入內核參數
device 選項我添加了如下設備:
- ich9-intel-hda:ich9 聲卡
- qemu-xhci:USB root hub,選用這個是因為它還支持 USB 3.0
- usb-tablet:貌似是用來模擬觸摸屏的,必須先給了 usb root hub 才能用這個選項
- e1000:e1000 網卡,網絡使用 network0
同時指定了這些內核參數:
- vga=917:使用 917 作為 vga mode,更改分辨率的意思。可通過 vga=ask 來讓內核詢問使用哪個模式。这个数字是 1600x900 顏色深度 32 的意思。但需要注意,在啟動時的詢問菜單中輸入的是十六進制,而在啟動時填入的內核參數是十進制。
- loglevel=3:設定內核的日誌等級,3 指僅輸出 ERROR 以及更重要日誌。
- panic=10:內核崩潰後,等待 10 秒自動重啟。
更多的內核參數可以查看 kernel.org 的 The kernel’s command-line parameters。
運行後就應該能看到 qemu 窗口,也看到系統的啟動了。
預安裝一些軟件
如果你並沒有怎麼修改,現在的 initrd 應該是沒什麼東西的。它甚至缺乏一些現代的命令(例如 iproute2)。那麼我們就以 iproute2 為例子,把它塞進 initrd 裡吧。
包依賴處理、下載
首先可以从 https://distro.ibiblio.org/tinycorelinux/13.x/x86_64/tcz
找到 iproute2.tcz
,然后检查一下依赖:
1 | > curl https://distro.ibiblio.org/tinycorelinux/13.x/x86_64/tcz/iproute2.tcz.dep |
應該會得到如下返回:
1 | db.tcz |
也就是說這個包依賴 db.tcz
,那麼繼續查下去
1 | > curl https://distro.ibiblio.org/tinycorelinux/13.x/x86_64/tcz/db.tcz.dep |
重複直到返回 404,我們應該就能得到一個包列表了:
1 | iproute2.tcz |
這就是遞歸依賴處理,人工操作一個兩個還好,但如果包比較多,依賴深度大,就會很麻煩,後期我們將會用程式來實現這個過程。
解壓、合并檔案到 initrd
把所需要的包都下載下來,然後用 squashfs-tools 解開
1 | for i in iproute.tcz db.tcz libdb.tcz |
unsquash 命令
- -f:指定文件
默認 unsquashfs 會把文件放到 squashfs-root
中
那么现在就可以把文件内容复制到 rootfs 中:
1 | cp -Rp "squashfs-root/usr/." "rootfs/usr/" |
cp 命令
- -R:原樣拷貝文件,不跟隨軟連結
- -p:保持文件的訪問控制符不變
完成
現在重複打包步驟,再次啟動虛擬機,在其中輸入 ip
命令,應該就有了。
下回分解
手動操作這個過程還是比較繁瑣。接下來會用到我自己寫的工具來構建這麼一個迷你發行版,也會解釋這個工具的工作方式。用它來構建的話過程會簡單很多。
可以訪問我的 GitHub 首頁倉庫獲取以及查閱幫助:tools/make-tinycore-linux
這個迷你發行版也在我的 GitHub 上:CattenLinger/jam.linux