我小時(shí)候用的電腦可不會整天開著等你。用完了就關(guān)機(jī),想再用的時(shí)候,按下開關(guān),一兩秒內(nèi)就開始讀盤了。那時(shí)候沒那么多服務(wù)要啟動,沒那么多驅(qū)動要加載,干凈利落。
到了2000年代初,SSD剛出來那陣子,啟動速度確實(shí)快了那么一段。但科技行業(yè)從來不會讓你閑著——硬件提速多少,軟件就有辦法吃掉多少。現(xiàn)在一臺16核怪獸配上高速SSD,從按下電源到系統(tǒng)完全就緒,該花一分鐘還是得花一分鐘。
![]()
所以我就在想,能不能反過來試試:Linux內(nèi)核留著,其他能砍的全砍掉。不是說什么都不剩,但確實(shí)能省掉一大堆東西。這念頭一動,就有了下面這個(gè)實(shí)驗(yàn)。
補(bǔ)充一句:按照互聯(lián)網(wǎng)的優(yōu)良傳統(tǒng),當(dāng)我想修兩個(gè)小細(xì)節(jié)的時(shí)候,搜到了一篇叫“Building a tiny Linux from scratch”的文章。作者用Rust語言,比我早一年干了差不多的事,值得一看。
Linux系統(tǒng)起來后做的第一件事,就是運(yùn)行一個(gè)叫“init”的程序。不管哪種init系統(tǒng),本質(zhì)上就是個(gè)普通的可執(zhí)行文件或者腳本,負(fù)責(zé)把其他進(jìn)程、配置什么的都拉起來。歷史上出現(xiàn)過好幾種不同方案,但說到底,它沒什么特殊的。
既然如此,我們就自己拿C寫一個(gè)。下面是init.c的全部代碼:引入標(biāo)準(zhǔn)輸入輸出、標(biāo)準(zhǔn)庫和系統(tǒng)重啟的頭文件,main函數(shù)里就干兩件事——往標(biāo)準(zhǔn)錯(cuò)誤輸出打印一句“Hello from init.c!”,然后調(diào)用reboot(RB_POWER_OFF)關(guān)機(jī)。
這個(gè)設(shè)計(jì)有個(gè)講究:如果init進(jìn)程退出了,內(nèi)核會直接panic掛掉。與其忙著循環(huán)等待或者無限期休眠,不如用reboot干干凈凈把虛擬機(jī)關(guān)掉。一句問候,一次關(guān)機(jī),簡潔到不能再簡潔。
接著要做一個(gè)initrd。現(xiàn)代Linux的啟動流程其實(shí)挺復(fù)雜的。網(wǎng)上資料不少,但很多都是20年前的老黃歷了。在我寫這篇文章的2026年,系統(tǒng)跑的是Linux 6.8上下版本,大致流程是這樣的:
引導(dǎo)加載程序先把內(nèi)核和一個(gè)叫initrd的臨時(shí)文件系統(tǒng)加載進(jìn)來。內(nèi)核會試著把initrd解壓成initramfs——在內(nèi)存里建一個(gè)根文件系統(tǒng),讓初始化工具能跑起來。然后內(nèi)核去找/init這個(gè)文件,要是找到了就執(zhí)行它,后面的事全交給它。要是沒找到,就換條路走:掛載root參數(shù)指定的根分區(qū),把devtmpfs掛到/dev目錄,再從那上面跑/init程序。還是不行的話,內(nèi)核panic。
現(xiàn)在主流發(fā)行版走的都是第一條路。那個(gè)initrd文件可不小——我自己的機(jī)器上,這個(gè)文件有73MB,用lsinitramfs看進(jìn)去,里面塞了2163個(gè)文件,各種模塊、固件全裝在里面,就為了掛載真正的文件系統(tǒng)之前做好準(zhǔn)備。
特別聲明:以上內(nèi)容(如有圖片或視頻亦包括在內(nèi))為自媒體平臺“網(wǎng)易號”用戶上傳并發(fā)布,本平臺僅提供信息存儲服務(wù)。
Notice: The content above (including the pictures and videos if any) is uploaded and posted by a user of NetEase Hao, which is a social media platform and only provides information storage services.