編譯最小linux系統

lm_y發表於2017-09-21
一,什麼是BabyLinux
二,為什麼要做這樣一個linux
三,什麼人適合讀這篇文件
四,應該具備的知識
五,linux系統引導過程簡介
六,編譯核心
七,編譯busybox
八,製作根檔案系統
九,製作ramdisk映象檔案
十,核心與busybox的整合
十一,安裝測試和內容調整
十二,babylinux中的BUG
十三,接下來要做的事情
十四,參考文獻

一,什麼是BabyLinux

BabyLinux 不是一個完整的發行版,他是利用原有的一套完整的linux系統的核心原始碼和編譯工具,利用busybox內建的強大功能,在一張軟盤上做的一個很小的 linux系統.他具備一個linux系統的基本特徵,支援linux系統最常用的一百多個命令,支援多種檔案系統,支援網路等等,你可以把他當做一張 linux起動盤和修復盤來用,你也可以把他當做一個靜態路由的路由器軟體,當然,你也可以把他當做一個linux玩具,向你的朋友炫耀 linux可以做的多麼小.我把他叫做BabyLinux因為他很小巧,小的很可愛,像一個剛剛出生的小baby.

二,為什麼要作這樣一個linux

先說說我一開始的想法,當我一開始接觸linux的時候,看到書上說,linux通常安裝只需要60M左右的空間,但是我發現裝在我硬碟上的Redhat 6.0確要佔據好幾百M的空間.為什麼我的linux這麼大呢? 後來我發現,裝在我機器上的那麼多東西只有不到30%是我平時常用的,還有30%是我極少用到的,另外的40%基本上是不用的.於是,我和大多數初學者一樣,開始抱怨,為什麼linux不能做的精簡一點呢?於是,我萌發了自己裁減系統的想法.可惜那個時候我還沒有聽說過有LFS和Debain.等到我積累了足夠的linux知識後,我開始製作這樣一個小系統.
製作這樣一個小系統最大的意義在於,你可以通過製作系統瞭解linux的啟動過程,學會 ramdisk的使用,讓你在短時間內學到更多的linux知識. 當然,你會得到很大的樂趣.這個專案只是做一個具有基本特徵的linux系統,如果你想自己做一個具有完整功能的linux,請閱讀Linux From Scratch (LFS)文件.

三,什麼人適合讀這篇文件

如果你是一個linux愛好者,並且很想了解 linux的啟動過程和系統的基本結構,而且是一個喜歡動手研究小玩意的人,那麼這個文件可以滿足你的需求. 如果你僅僅是用linux來做一些普通的日常工作,而不在乎你的linux到底怎麼工作,那麼這份文件也許不太適合你.另外,如果你是linux愛好者, 但是目前還是一個剛剛入門的newbi,我建議你先把linux命令學好.不過我想我會盡可能的把這份文件寫詳細一些,如果你有足夠的毅力,或許一個 newbi也能成功做一個babylinux.或者,你遇到一件很不巧的事情,比如你的老婆來例假了,你的這個週末就泡湯了,那麼閱讀這篇文件並做一個 linux小玩具可以打發你的時間.

四,應該具備的知識

在做一個babylinux之前,你應當已經會應用linux最常用的命令.並且至少有一次成功編譯並安裝系統核心的經歷,會通過編譯原始碼來安裝軟體. 如果你具備了這些條件,那麼做這樣一個小系統會很順利,如果你還沒有掌握這些知識,你可能會遇到一些困難.但是隻要有毅力,也可以成功.你不需要具備程式設計的知識,因為我的目標是:讓具有中等以上linux水平的愛好者可以通過閱讀文件輕鬆完成這個專案.關於一張軟盤上的linux還有一個很著名的 linux叫LOAP (Linux On A
Floppy) 但是他是由比較專業的人員需要編寫很多程式完成的.而且沒有關於他製作過程的文件.

五,linux系統引導過程簡介

首先,主機板的BIOS會讀取硬碟的主開機記錄(MBR),MBR中存放的是一段很小的程式,他的功能是從硬碟讀取作業系統核心檔案並執行,因為這個小程式太小了,因此通常這個小程式不具備直接引導系統核心的能力,他先去引導另一個稍微大一點的小程式,再由這個大一點的小程式去引導系統核心.在linux系統中這樣的小程式有LILO和GRUB.在這個專案中,我決定用LILO來做系統載入程式.在軟盤上啟動linux系統的過程和在硬碟上啟動的過程相似.

Linux系統核心被載入程式裝入核心並執行後,linux核心會檢測系統中的各種硬體.並做好各種硬體的初始化工作,使他們在系統正式執行後能正常工作.之後核心做的最後一個工作是執行
/sbin 下的init程式,init是英文單詞initialization(初始化)的簡稱,init程式的工作是讀取/etc/inittab檔案中描述的指令,對系統的各種軟硬體環境做最初化設定.最後執行mingetty等待使用者輸入使用者名稱登入系統.所有的工作就這麼簡單,雖然linux啟動的時候有很多內容,看上去十分高深,但是都不過是對這個過程的擴充.明白了這個道理,你可以寫一些指令碼程式讓他在系統啟動的特定時間執行完成任務.事實上系統核心並不關心/sbin下的init是不是真的init,只要是放在/sbin下名叫init的可執行程式他都可以執行.可以做以下實驗:

編寫一個非常簡單的C程式:

main()
{
printf(“hello,world!\n”);
}

儲存後以init.c儲存他,並用gcc編譯.
#gcc –-static -o init init.c
這裡的--static 引數告訴gcc把這個程式靜態聯接,這樣這個程式不倚賴任何庫就能執行.把編譯好的init程式拷貝到/sbin下,備份好原來的那個.重新啟動系統最後系統的輸出結果是: hello,world!
然後停在那裡.做這個實驗以前先確定你知道如何把系統恢復到原來的狀態,有一個簡單的方法,在核心啟動前給他加上init=引數,比如你原先的init被你改成了init.bak 只要在啟動的時候給核心加上init=/sbin/init.bak就可以用原來的init程式啟動系統.
做完以上實驗,就明白了核心和init程式之間的關係.此外,init程式不一定是一個二進位制可執行程式,他可以是一個bash指令碼,一個指向另一個程式的聯接,他的位置也並不一定要在/sbin下,只要在啟動核心時,給核心加上init引數就能被執行,比如,開始時給核心加上init= /bin/bash引數,核心在最後一步就直接執行bash給出提示符,不用登入系統就可以輸入命令了.其功能類似單使用者模式啟動系統. /sbin/init 程式只是核心預設執行的第一個程式.

六,編譯一個linux系統核心

1,編譯前的規劃和準備

在編譯核心前,請先確定你的需求,把你的需求羅列成一張詳細的表格.你需要讓核心支援什麼硬體,支援多少種分割槽型別和檔案系統,支援哪些網路卡,支援哪些網路協議.等等.請儘可能詳細的羅列這些內容,但是你也不要太貪心,因為你所有能利用的空間只有1440K,如果你編譯出一個大於1440K或很接近這個數字的核心,你的這個專案就不能完成了,你已經沒有空間再放ramdisk映象檔案,除非你原意再多出一張軟盤,做一個兩張軟盤的小linux系統.對於音效卡驅動之類,我勸你還是放棄吧,因為一個音效卡驅動也許只讓你的核心增大了十多K,但是你有了一個音效卡驅動就務必要有一個播放器吧,否則音效卡驅動就沒有意義, 可一個播放器的大小可不是一張軟盤可以裝得下的.在我先前製作的babylinux核心有900多K,其中,檔案系統部分站了大部分,因為我的目標是把他做成一個系統修復盤.因此我在核心中編譯7種檔案系統的支援,每減少一個檔案系統就可以減小几十甚至200多K的核心大小.越是複雜,越是安全的檔案系統,其支援模組也越大,比如在linux下FAT模組只有32K,VFAT只有17K,但是ext3的模組就有86K,JFS達到216K, reiserfs模組是224K,可以想像,編譯一個支援7個檔案系統的900多K的核心,檔案系統部分就佔了600K以上的空間,所以如果某一個檔案系統是你根本不用的,那麼還是不要編譯進核心把,這樣至少可以省下100多K的空間.對於其他的驅動,比如網路卡,通常大小隻有8,9K,最大的也不過10多 K,因此可以把常用的網路卡晶片的驅動都編譯進去.另外如果你想讓你的babylinux支援U盤,那麼scsi的驅動模組也是不可小看的,他通常要接近 150K,因為U盤是被當做scsi裝置來驅動的.另外你還需要讓你的核心支援即插即用,這些都是不小的空間開銷,我的建議是你放棄一兩個你不用的檔案系統.總之,你最後編譯出來的核心大小最好不要超過900K,否則你在busybox裡只能編譯進去很少的命令.

在我編譯的busybox 中,我編譯進去120多個命令,基本上把busybox支援的命令都包括進去了.加上小系統所必需的檔案系統目錄,/dev下的裝置檔案,以及/etc下幾個必需的配置檔案,做成ramdisk壓縮後的大小是440多K, 加上900K左右的核心剛好可以放入一張1440K軟盤,請注意,你應該留下至少50K的空間,因為我們要在軟盤上建立一個ext2檔案系統,而檔案系統本生需要佔據大概25K的磁碟空間.另外lilo的引導檔案boot.b的大小是5.7K,還有裝上lilo後自動產生的map檔案也要10多K的空間, map檔案的具體大小由核心安裝的實際大小決定,通常不會超過30K.
綜上所述,請遵循下面的公式:

核心大小+檔案系統壓縮印象檔案+50K <= 1440K

另外一點需要說明的是:以上所羅列的檔案系統模組大小是察看我現在使用的Redhat 9 的
/lib/modules下的模組檔案得到的,實際編譯進核心大小會小一點,因為我們用make bzImage
在核心原始碼目錄樹下生成的核心是經過壓縮過的.

如果你對以上說的內容不太明白也沒有關係,我會在下面的內容中做詳細的說明.

2,必需編譯進核心的內容

首先,我們製作的這個小系統是基於一張軟盤的,因此,你的核心必需支援軟盤.另外對IDE硬碟和cdrom的支援也是不可少的,否則做出來的 babylinux就沒有實用價值,因為他不能訪問硬碟和光碟上的內容這樣的linux雖然可以做的更小,但是製造一個完全沒有用的東西是浪費時間.其他的包括framebuffer等,如果你需要支援在字元介面下以高解析度顯示,以看到更多的螢幕內容,那麼就必需把framebuffer支援編譯進核心,此外在高解析度下使用的8x8字型也必需編譯進去.否則即使你給核心傳遞了vga= 引數,核心會因為沒有可用的小字型而自動轉跳到低解析度模式下,這是以前困擾我好幾天想不明白的事情,後來通過反覆試驗才明白原來是缺少字型的文體.這裡我先大致提一下需要注意的事情.在下一小節具體編譯時,我會繼續就某些細節問題說明.

3,關於核心的版本

我是在Redhat 9 linux系統下打造的babylinux小系統.使用的是Redhat 9 自帶的2.4.20版的核心.
為什麼我不用最新的2.6的核心?
一開始我也企圖用最新的核心,但是通過試驗我發現,在用最新的2.6.9核心的情況下,我編譯一個all-no的(即所有內容都選N,不支援任何硬體,只有一個最基本的核心)最小化核心就要460K左右,如果我在這個基礎上再加入幾種檔案系統和必要的驅動,那麼核心的大小就不能裝下一張1440K
的軟盤,而我用2.4.20的核心編譯一個最小化的核心只需要217K,的大小.如果優化了gcc引數他還能再小些.這樣我就立即省下了200多K的空間, 在平時,200多K的內容微不足道,但是在babylinux裡,這個數目是整個空間的 1/7,相當於一個reiserfs檔案系統模組的大小.當然,我也嘗試了2.2以及更老的核心,但是他們缺少我需要的東西,因此最後權衡下來用2.4的核心是比較合理的.如果你用的是2.6核心的FC系統,那麼最好還是去下載一個2.4版的核心,www.kernel.org 有各個時期的核心可以下載.

4, 核心的配置

如果你對linux核心的配置和編譯已經很熟悉了,請跳過這一段,直接看busybox的編譯.

以root身份登入系統
進入/usr/src/linux目錄
[root@gucuiwen root]# cd /usr/src/linux
如果你下載了一個2.4版本的核心,為了避免麻煩,請將他拷貝到/usr/src下,然後接壓縮,再做一個指向他的名為linux的連結.雖然這並不是必需的,但是根據我以往的經驗,如果我把linux原始碼放在其他目錄下解開並編譯,偶然會有一些莫名其妙的小問題發生.

#cp linux-2.4.20.bz2 /usr/src/
#cd /usr/src
#tar xfvj linux-2.4.20.bz2
如果是tar.gz格式,可以這樣解開
#tar xfvz linux-2.4.20.tar.gz
為了方便,做一個到目錄linux-2.4.20的連線:
#ln -s linux-2.4.20 linux
進入linux原始碼目錄:
#cd linux
清理原始碼樹:
#make mrproper
執行配置程式:
#make xconfig

code maturity level options
先選擇N,當我們配置好常規的東西,要加入framebuffer支援時再將這一項選擇Y,因為在2.4.20中,framebuffer支援尚屬於實驗性程式碼.如果不在code maturity level options選擇為Y,將不能配置framebuffer.

Loadable module support
選擇N,為了簡化系統的製作,我在這個專案中不選擇可載入核心模組的支援.

processor type and features

processor family 中選擇你需要的CPU型別,如果你想讓老至386,新到P4的CPU都能執行babaylinux那麼請選擇386CPU,否則請按自己的實際情況選擇.

其他選項都選擇N.這些在babylinux中都是不需要的.

General setup
networking support 選擇Y
PCI support 選擇Y 除非你不用PCI裝置,不過一般人都是需要的,因為現在網路卡大部分是PCI的.

相關文章