這份筆記記錄了從0開始構(gòu)建一個最小根文件系統(tǒng)的流程,從而達到分析其目錄結(jié)構(gòu)及文件的目的,基于的kernel版本為2.6.35
1.結(jié)構(gòu)總覽
如圖
2.安裝busybox
可以從官網(wǎng)https://busybox.net/downloads/ 下載到源碼,我們使用2015年的1.24.1版本。busybox這個項目借鑒了很多kernel的地方,比如配置部分和Makefile等,我們只要按照kernel的方法操作它就行了
- 進入源碼目錄,打開Makefile檢查架構(gòu)和交叉編譯工具鏈,利用/在vim中搜索CROSS_COMPILE和ARCH,將其改為
ARCH = arm
CROSS_COMPILE = /usr/local/arm/arm-2009q3/bin//arm-none-linux-gnueabi-
- 然后直接make menuconfig,開始配置busybox。首先進入Busybox Settings->Build Options 配置使用靜態(tài)鏈接庫,因為我們要移植到開發(fā)板所以不要使用動態(tài)鏈接庫
再進入Busybox Settings->Busybox Library Tuning,設(shè)置為vi風(fēng)格
進入Linux Module Utilities,設(shè)置模塊化,注意要取消 Simplified modutils,然后選擇下面的子選項
進入Linux System Utilities,確認mdev下面的子選項都被選中了
進入 Busybox Settings->Installation Options (“make install” behavior),修改busybox的安裝路徑
- 配置完了直接編譯,
make -j4
,發(fā)現(xiàn)報錯了:
看來是sync.c報錯了,google一下,發(fā)現(xiàn)這個sync功能并不是什么特別有用的,我們直接在menu config中將其屏蔽即可。然后再編譯,發(fā)現(xiàn)沒有報錯 - 然后輸入
make install
來安裝busybox,這一步主要的目的是把編譯生成的一大坨可執(zhí)行文件、和依賴的庫文件,妥當(dāng)?shù)陌惭b到我們指定的目錄下(即根文件系統(tǒng)目錄)
3.添加/etc/inittab
/etc目錄里面是各個程序的配置文件,眾多程序在運行時需要根據(jù)配置文件來指導(dǎo)它們的行為
此處的/etc/inittab就是busybox的配置文件之一,busybox運行時將根據(jù)/etc/inittab來指導(dǎo)自己的行為。如果我們要添加自己的自啟應(yīng)用程序,并不推薦inittab,推薦rc*.d,詳見第5節(jié)。
- 首先手動創(chuàng)建/etc目錄,然后在里面創(chuàng)建/etc/inittab文件,并向其內(nèi)部添加:
#sjh:這是一個典型的inittab內(nèi)容
#first:run the system script file
::sysinit:/etc/init.d/rcS
::sysinit:/bin/login
::askfirst:-/bin/sh
::ctrlaltdel:-/sbin/reboot
#umount all filesystem
::shutdown:/bin/umount -a -r
#restart init process
::restart:/sbin/init
- inittab文件內(nèi)容是嚴格按照一定的格式的,非#開頭的就是正式語句了,每一行都是一個配置項
- 配置項的標準格式為,id:runlevels:action:process 其中,冒號代表分隔符,分隔開各個部分;id和runlevels不是很重要,一般能省略,這就是為什么上面這段代碼行首有兩個冒號的原因;action代表一個條件/狀態(tài);process代表操作
- ::sysinit:/etc/init.d/rcS的意思是:當(dāng)條件狀態(tài)為“訪問控制臺前的初始化”時,執(zhí)行“/etc/init.d/rcS”
- ::sysinit:/bin/login的意思是:當(dāng)條件狀態(tài)為“訪問控制臺前的初始化”時,執(zhí)行“/bin/login”即啟動用戶登錄程序
- ::askfirst:-/bin/sh的意思是:當(dāng)條件狀態(tài)為“啟動程序前(不太理解?)”是,執(zhí)行“-/bin/sh”
- ::ctrlaltdel:-/sbin/reboot的意思是:當(dāng)條件狀態(tài)為“重啟”時,執(zhí)行“-/sbin/reboot”
- ::shutdown:/bin/umount -a -r的意思是:當(dāng)條件狀態(tài)為“關(guān)機”時,執(zhí)行“/bin/umount -a -r”(意思是取消掛載的目錄)
- ::restart:/sbin/init的意思是:當(dāng)條件狀態(tài)為“重啟init(busybox)”時,執(zhí)行“/sbin/init”(init其實就是busybox)
- 總之,busybox在運行時會不斷的循環(huán)判斷,一旦當(dāng)前符合條件狀態(tài)了inittab中的某一個配置項,它就會執(zhí)行相應(yīng)的操作??梢姡琲nittab文件對于busybox相當(dāng)重要
4.添加/etc/init.d/rcS
/etc/init.d/rcS是被busybox調(diào)用的控制臺初始化程序,這個文件是一個shell腳本,在開機訪問控制臺前它將被busybox執(zhí)行,可以認為rcS是一個開機就執(zhí)行的初始化程序
如果我們要添加自己的自啟應(yīng)用程序,并不推薦rcS,推薦rc*.d,詳見第5節(jié)
- 首先手動創(chuàng)建/etc/init.d/,然后在里面創(chuàng)建rcS,并向其內(nèi)部添加
#!/bin/sh
PATH=/sbin:/bin:/usr/sbin:/usr/bin
runlevel=S
prevlevel=N
umask 022
export PATH runlevel prevlevel
mount -a
echo /sbin/mdev > /proc/sys/kernel/hotplug
mdev -s
/bin/hostname -F /etc/sysconfig/HOSTNAME
ifconfig eth0 192.168.1.3
- 首先一上來定義了三個變量PATH、runlevel、prevlevel,并將其導(dǎo)出為環(huán)境變量
- PATH這個環(huán)境變量代表應(yīng)用程序的默認路徑,當(dāng)我們執(zhí)行應(yīng)用程序(如 ls)時可以不輸入路徑,busybox會去這個路徑內(nèi)搜索。PATH=/sbin:/bin:/usr/sbin:/usr/bin表示將應(yīng)用程序默認路徑設(shè)置為/sbin、/bin、/usr/sbin、/usr/bin,冒號為分隔符
- runlevel這個環(huán)境變量表示Linux系統(tǒng)的運行級別(模式)設(shè)置,比如0代表關(guān)機,1代表單用戶root模式,2代表多用戶模式,我們這里設(shè)置的S代表的也是單用戶root模式
- prevlevel這個環(huán)境變量不是很重要
- umask 022表示設(shè)置umask值為022,umask決定了用戶創(chuàng)建新文件時,新文件的權(quán)限,一般來說默認的022夠用了
- mount -a表示掛載指定的文件系統(tǒng),具體由/etc/fstab(見后文)指定
- echo /sbin/mdev > /proc/sys/kernel/hotplug表示創(chuàng)建符號鏈接mdev,指向hotplug,這一步的根本目的是實現(xiàn)熱插拔設(shè)備功能,其實就是當(dāng)驅(qū)動模塊被加載時,自動生成/dev下的設(shè)備文件
- mdev -s,表示開啟掃描驅(qū)動設(shè)備模塊,如果掃描到了就自動生成/dev下的設(shè)備文件。這一步和上一步其實就是開啟mdev的“自動創(chuàng)建設(shè)備文件功能”
- /bin/hostname -F /etc/sysconfig/HOSTNAME表示執(zhí)行了hostname程序,把當(dāng)前主機的名字設(shè)置為HOSTNAME(見后文)文件中的主機名,-F是參數(shù),表示去文件中獲取主機名
- ifconfig eth0 192.168.1.3表示設(shè)置ip地址
5.添加/etc/rc*.d目錄(可選)
這是一種當(dāng)前非常流行的開機啟動設(shè)置方式,/etc/rc*.d中的腳本將被開機啟動。rc*.d
中的*
代表了了啟動優(yōu)先級
- 如果文件系統(tǒng)中有這類目錄,那么我們應(yīng)該按照這個方法設(shè)置開機啟動程序。如果本來就沒有,那么也沒必要強行添加,也能在
/etc/inittab
或/etc/init.d/rcS
設(shè)置開機啟動 - 關(guān)于添加開機啟動的注意點:
- 能后臺運行盡量后臺運行,前臺運行會占用控制臺,如果需要后臺運行,則只需在指令后面加&即可,如
/test/hello_static &
- 開機啟動的程序中,應(yīng)該使用全路徑,因為只有登錄后,當(dāng)前目錄才會進入
~/
,而開機啟動的程序有可能在登錄前運行(也有可能根本不登錄),所以使用全路徑比較保險
6.添加/etc/fstab
該文件指定了系統(tǒng)初始化時應(yīng)該掛載的文件系統(tǒng),
首先手動創(chuàng)建/etc/fstab,并向其內(nèi)部添加:
# <file system> <mount point> <type> <options> <dump> <pass>
proc /proc proc defaults 0 0
sysfs /sys sysfs defaults 0 0
tmpfs /var tmpfs defaults 0 0
tmpfs /tmp tmpfs defaults 0 0
tmpfs /dev tmpfs defaults 0 0
- 上面幾欄分別代表要掛載的設(shè)備、掛載的地點(目錄)、按什么類型掛載、選項
- 其實這些都是虛擬文件系統(tǒng),具體和驅(qū)動有關(guān)
7.添加/etc/sysconfig/HOSTNAME和/etc/profile
- /etc/sysconfig/HOSTNAME是系統(tǒng)初始化程序rcS讀取的一個配置文件,里面是用戶的名字
- /etc/profile是一個腳本程序,被busybox調(diào)用,它可以在控制臺中顯示用戶的名字,如圖:
- 手動創(chuàng)建這兩個文件,往HOSTNAME中寫用戶名,往profile中填充:
# Ash profile
# vim: syntax=sh
# No core files by default
ulimit -S -c 0 > /dev/null 2>&1
USER="`id -un`"
LOGNAME=$USER
PS1='[\u@\h \W]\# '
PATH=$PATH
HOSTNAME=`/bin/hostname`
export USER LOGNAME PS1 PATH
8.添加/proc、/sys、/tmp、/var、/dev
這些目錄都將作為系統(tǒng)的虛擬文件系統(tǒng)的掛載點,自己手動創(chuàng)建即可,busybox的mount -a 指令會根據(jù)/etc/fstab文件自動掛載虛擬文件系統(tǒng)到這些目錄
- /proc的作用是展示內(nèi)核運行時的一些數(shù)據(jù)結(jié)構(gòu),它們將以文件的方式呈現(xiàn)在/proc中,開發(fā)者可以通過觀察其中的文件來了解內(nèi)核的運行信息。虛擬文件的內(nèi)容都是動態(tài)創(chuàng)建的,它們并非完全是只讀的,前面介紹的寫/proc/sys/kernel/printk 可以改變 printk的打印級別
- /sys的作用和/proc完全相同,它是/proc的升級版本,里面的虛擬文件基本都可以讀寫
9.(可選)添加/etc/passwd、/etc/shadow
這兩個文件內(nèi)部配置了用戶和密碼相關(guān)的設(shè)置,一般的嵌入式系統(tǒng)用不到這個功能。如果需要使用可以在網(wǎng)上搜索這兩個文件的格式
10.添加/lib
在主機中交叉編譯出來的應(yīng)用程序若使用了靜態(tài)鏈接庫,則可以直接在開發(fā)板上跑。而使用了動態(tài)鏈接的則不行,因為執(zhí)行時在需要開發(fā)板上加載庫文件。所以在rootfs中添加動態(tài)鏈接庫文件是必不可少的
- 首先·要獲取庫文件,一般來說在交叉編譯工具鏈中是有提供的。我們用的arm-2009q3工具鏈的動態(tài)鏈接庫在/usr/local/arm/arm-2009q3/arm-none-linux-gnueabi/libc/lib目錄下。其他的一些交叉編譯工具鏈中動態(tài)鏈接庫的目錄不一定在這里,要去找一下。找的方法就是find
- 復(fù)制動態(tài)鏈接庫到roots/lib目錄下。復(fù)制時要注意參數(shù)用-rdf,主要目的就是符號鏈接復(fù)制過來還是符號鏈接
- (可選)當(dāng)使用norflash,空間不足時,我們可以裁剪動態(tài)鏈接庫中的調(diào)試符號信息。裁剪的方法是使用交叉編譯工具鏈中的arm-none-linux-gnueabi-strip工具,我們在lib目錄下輸入arm-none-linux-gnueabi-strip *so*,把所有名字中的含有so的庫文件都裁剪掉他們的調(diào)試符號信息。裁完發(fā)現(xiàn)lib文件夾大小由3.8mb縮為了3.0mb,而zImage一共也才3.5mb,可見裁掉的這些空間非常可觀
本站僅提供存儲服務(wù),所有內(nèi)容均由用戶發(fā)布,如發(fā)現(xiàn)有害或侵權(quán)內(nèi)容,請
點擊舉報。