1. 根文件系統(tǒng)布局
嵌入式 Linux 根文件系統(tǒng)布局,建議還是按照FHS標(biāo)準(zhǔn)來安排,事實上大多數(shù)嵌入式Linux都是這樣做的。但是,嵌入式系統(tǒng)可能并不需要桌面/服務(wù)器那樣龐大系統(tǒng)的全部目錄,可以酌情對系統(tǒng)進行精簡,以簡化Linux的使用。如嵌入式Linux文件系統(tǒng)中通常不會放置內(nèi)核源碼,因而存的 常不會放置內(nèi)核源碼,因而存的 常不會放置內(nèi)核源碼,因而存放源碼的/usr/src目錄是不必要的, 甚至連頭文件也不需要,即/usr/include目錄也不必要;但是/bin、/dev 、/etc、/lib 、/proc 、/sbin、/usr幾個目錄是不可或缺的。
所以,允許嵌入式 Linux 對系統(tǒng)目錄結(jié)構(gòu)進行精簡,以適應(yīng)具體用場合的需求,一個典型的嵌入式Linux根文件系統(tǒng)目錄如下所示:
要構(gòu)建一個可用的Linux根文件系統(tǒng),需要的二進制和庫都不少,完全從零開始也是不現(xiàn)實的,推薦參考其它現(xiàn)有可用的文件系統(tǒng),在原基礎(chǔ)上按需修改;或者使用文件系統(tǒng)制作工具如 BusyBox 來實現(xiàn)文件系統(tǒng)的生成。
2. 使用BusyBox生成二進制工具
2.1. 獲取BusyBox源碼
Busybox的官方源碼下載路徑為:https://busybox.net/downloads/。這里以下載busybox-1.29.3.tar.bz2為例。
2.2. 配置BusyBox
解壓源碼,進入根目錄
?
$?tar?jxvf?busybox-1.29.3.tar.bz2 $?cd?busybox-1.29.3/
?
首先,執(zhí)行:
?
$?make?menuconfig
?
進入圖形化配置界面:
2.2.1.選擇編譯靜態(tài)庫
進入Settings --->使用空格鍵選擇編譯靜態(tài)庫
?
---?Build?Options????????????????????????????????????????????? [*]?Build?static?binary?(no?shared?libs)??
?
如圖:
2.2.2.選擇交叉編譯工具鏈
在Settings ---> 設(shè)置項下,填寫交叉編譯工具鏈前綴
2-2-3. 選擇安裝目錄
在Settings --->設(shè)置項下,找到
?
---?Installation?Options?("make?install"?behavior)? ????What?kind?of?applet?links?to?install?(as?soft-links)??--->?? (./_install)?Destination?path?for?'make?install'?(NEW)??
?
默認(rèn)為當(dāng)前目錄下目錄,這里我使用默認(rèn)_install目錄:
2-2-4. 編譯安裝
退出保存后,執(zhí)行編譯make,大概幾分鐘后編譯完成,執(zhí)行make install,很快就會安裝完成:
入_install目錄,查看生成的文件
新建一個目錄用來存放制作的根文件系統(tǒng),可以命名為rootfs。將利用BusyBox生成的二進制文件及目錄,即_install目錄下的所有文件及目錄復(fù)制到rootfs目錄下。
3. 構(gòu)建根文件系統(tǒng)
使用BusyBox編譯后,僅有 bin、sbin、usr這 3個目錄和軟鏈接linuxrc,目錄里都是二進制命令工具,這還不足以構(gòu)成 一個可用的根文件系統(tǒng),必須進行其它完善工作,才能構(gòu)建一個可用的根文件系統(tǒng)。
3-1. 完善目錄結(jié)構(gòu)
根據(jù)典型嵌入式Linux根文件系統(tǒng)目錄,在rootfs目錄中創(chuàng)建其他目錄
?
$?mkdir?dev?etc?lib?proc?sys?tmp?var
?
3-2. 添加C運行庫文件
庫文件可直接從交叉工具鏈獲取,一般在工具鏈的libc/lib/目錄下。我這里是在ubuntu下安裝的Linaro的交叉工具鏈:
庫文件是在/usr/arm-linux-gnueabihf/lib/目錄下,拷貝動態(tài)鏈接庫文件(.so文件)到新制作的根文件系統(tǒng)根目錄下/lib目錄里:
?
$?cp?-a??/usr/arm-linux-gnueabihf/lib/*so*?./lib/
?
這里只是拷貝動態(tài)鏈接庫。一般開發(fā)程序使用動態(tài)編譯需要板子上動態(tài)庫的支持才能運行,所以拷貝動態(tài)庫。而靜態(tài)庫一般在靜態(tài)編譯的時候用到,由于交叉編譯的工作放在了PC上所以板子上不需要靜態(tài)庫,所以沒有必要拷貝,這樣還可以減小根文件系統(tǒng)的體積。
一般使用gcc編譯后的可執(zhí)行文件、目標(biāo)文件和動態(tài)庫都帶有調(diào)試信息和符號信息,這些在調(diào)試的時候用到,但是卻增大了文件的大小。通常在PC上調(diào)試,或者調(diào)試時使用這些帶有調(diào)試信息和符號信息的庫文件,程序發(fā)布后使用去掉這些信息的庫文件,可以大大縮小根文件系統(tǒng)的體積。這里我們?nèi)サ暨@些信息,方法是使用strip工具:
?
$?arm-linux-gnueabihf-strip?./*
?
3-3. 添加初始化配置腳本
初始化配置腳本放在在/etc目錄下,用于系統(tǒng)啟動所需的初始化配置腳本。BusyBox提供了一些初始化范例腳本,在examples/bootfloppy/etc/目錄下。將這些配置文件復(fù)制到 ”目錄下。將這些配置文件復(fù)制到 ”目錄下。將這些配置文件復(fù)制到新制作的根文件系統(tǒng)etc目錄下
?
cp?-a?../busybox/busybox-1.29.3/examples/bootfloppy/etc/*?etc/
?
添加后如圖所示:
3-3-1. 修改/etc/inittab文件
/etc/inittab文件是init進程解析的配置文件,通過這個配置文件決定執(zhí)行哪個進程,何時執(zhí)行。將文件修改為:
?
#?系統(tǒng)啟動時 :/etc/init.d/rcS #?系統(tǒng)啟動按下Enter鍵時 :-/bin/sh #?按下Ctrl+Alt+Del鍵時 :/sbin/reboot #?系統(tǒng)關(guān)機時 :/sbin/swapoff?-a :/bin/umount?-a?-r #?系統(tǒng)重啟時 :/sbin/init
?
以上內(nèi)容定義了系統(tǒng)啟動時,關(guān)機時,重啟時,按下Ctrl+Alt+Del鍵時執(zhí)行的進程。
3-3-2. 修改/etc/init.d/rcS文件
?
#!?/bin/sh #?掛載?/etc/fstab?中定義的所有文件系統(tǒng) /bin/mount?-a #?掛載虛擬的devpts文件系統(tǒng)用于用于偽終端設(shè)備 /bin/mkdir?-p?/dev/pts /bin/mount?-t?devpts?devpts?/dev/pts #?使用mdev動態(tài)管理u盤和鼠標(biāo)等熱插拔設(shè)備 /bin/echo?/sbin/mdev?>?/proc/sys/kernel/hotplug #?掃描并創(chuàng)建節(jié)點 /sbin/mdev?-s
?
3-3-3. 修改/etc/fstab文件
/etc/fstab文件存放的是文件系統(tǒng)信息。在系統(tǒng)啟動后執(zhí)行/etc/init.d/rcS文件里/bin/mount -a命令時,自動掛載這些文件系統(tǒng)。內(nèi)容如下:
?
#????? ???? ???? ???? ???? ????? proc??????????????????/proc??????????proc?????defaults???????0?????????0 sysfs?????????????????/sys???????????sysfs????defaults???????0?????????0 tmpfs?????????????????/tmp???????????tmpfs????defaults???????0?????????0 tmpfs?????????????????/dev???????????tmpfs????defaults???????0?????????0
?
注:這里我們掛載的文件系統(tǒng)有三個proc、sysfs和tmpfs,在內(nèi)核中proc和sysfs默認(rèn)都支持,而tmpfs是沒有支持的,我們需要添加tmpfs的支持。
3-3-4. 修改/etc/profile文件
/etc/profile文件作用是設(shè)置環(huán)境變量,每個用戶登錄時都會運行它。將文件內(nèi)容修改為:
?
#?主機名 export?HOSTNAME=zyz #?用戶名 export?USER=root #?用戶目錄 export?HOME=/root #?終端默認(rèn)提示符 export?PS1="[$USER@$HOSTNAME:$PWD]#?"???? #?環(huán)境變量 export?PATH=/bin:/sbin:/usr/bin:/usr/sbin #?動態(tài)庫路徑 export?LD_LIBRARY_PATH=/lib:/usr/lib:$LD_LIBRARY_PATH
?
因為指定了root用戶的家目錄為/root,所以需要創(chuàng)建該目錄,否則執(zhí)行cd ~時會失敗
?
$?mkdir?root
?
登錄系統(tǒng)后效果為:
?
... Please?press?Enter?to?activate?this?console. [root@zyz:/]# [root@zyz:/]#?cd?~ [root@zyz:/root]# [root@zyz:/root]#?echo?$PATH /bin:/sbin:/usr/bin:/usr/sbin
?
至此,根文件系統(tǒng)就基本構(gòu)建好了。
4. 制作根文件系統(tǒng)鏡像
4-1. 根文件系統(tǒng)類型
如果文件系統(tǒng)已經(jīng)布局完成, 則可以發(fā)到目標(biāo)中了。通常會制作一個鏡像然后通過某種方式固化到目標(biāo)系統(tǒng)中,具體采用什么樣的形發(fā)布需要根據(jù)資源狀況、內(nèi)核情況和系統(tǒng)需求等方面進行裁決:
(1)硬件方面,至少需要考慮主存儲介質(zhì)的類型和大小如Flash是NOR Flash還是NAND Flash,RAM的大小等。
(2)內(nèi)核方面, 則需考慮所裁剪后的支持哪些文件系統(tǒng)采用中最合適, 能滿足性、速度等要求。
(3)系統(tǒng)需求方面,要考慮運行速度、是否可寫壓縮等因素。常見的可用于根文件系統(tǒng)類型有ramdisk 、cramfs、jffs2 、yaffs/yaffs2和ubifs等,各類型的特性如表所列。
盡管文件系統(tǒng)固件以某一種文件系統(tǒng)的鏡像發(fā)布,但是整個文件系統(tǒng)實際上還是并存多種邏輯文件系統(tǒng)的。例如,一個系統(tǒng)根文件系統(tǒng)以ubifs掛載,但是/dev目錄卻是以tmpfs掛載的、/sys目錄掛載的是sysfs文件系統(tǒng)。現(xiàn)在,似乎ubifs是一種趨勢。
4-2. 制作UBIFS根文件系統(tǒng)鏡像
Linux下制作UBIFS的命令有兩個,mkfs.ubifs和ubinize。mkfs.ubifs,將一個目錄制作為UBIFS文件系統(tǒng)。使用范例:
?
$?mkfs.ubifs?-m?2048?-e?128KiB?-c?4096?-r?./rootfs?-o?rootfs.ubifs
?
其中:
?
-r,?-d,?--root=DIR???????build?file?system?from?directory?DIR(目錄) -m,?--min-io-size=SIZE???minimum?I/O?unit?size(最小輸入輸出單元大小) -e,?--leb-size=SIZE??????logical?erase?block?size(邏輯擦除塊大小) -c,?--max-leb-cnt=COUNT??maximum?logical?erase?block?count(最大邏輯擦除塊數(shù)目) -o,?--output=FILE????????output?to?FILE(輸出文件)
?
所以制作ubifs鏡像文件,需要知道3個關(guān)鍵參數(shù),即最小輸入輸出單元大小,邏輯擦除塊大小,最大邏輯擦除塊數(shù)目,其中最大邏輯擦除塊數(shù)目可由Flash分區(qū)大小和邏輯擦除塊大小計算出來,這些信息可以通過u-boot命令查看:
?
=>?mtdparts?default =>?ubi?part?rootfs
?
ubinize,將mkfs.ubifs制作的UBIFS文件系統(tǒng)制作成含有卷標(biāo)的可以直接燒寫在Flash上的鏡像。使用范例:
?
$?ubinize?-m?2048?-p?128KiB?ubinize.cfg?-o?rootfs_ubifs.img
?
其中:
?
-o,?--output=?????output?file?name(輸出文件) -p,?--peb-size= ???????size?of?the?physical?eraseblock?of?the?flash(物理擦除塊大小) ?????????????????????????????this?UBI?image?is?created?for?in?bytes, ?????????????????????????????kilobytes?(KiB),?or?megabytes?(MiB) ?????????????????????????????(mandatory?parameter) -m,?--min-io-size= ????minimum?input/output?unit?size?of?the?flash ?????????????????????????????in?bytes
?
這里需要兩個參數(shù)物理擦除塊大小和最小輸入輸出單元大小。ubinize.cfg是配置文件,內(nèi)容如下:
?
[ubifs] mode=ubi image=rootfs.ubifs vol_id=0 vol_size=1024MiB vol_type=dynamic vol_name=rootfs vol_flags=autoresize
?
說明:
?
[ubifs] mode=ubi image=rootfs.ubifs???????#?mkfs.ubi生成的源鏡像? vol_id=0?????????????????#?卷號 vol_size=1024MiB?????????#?卷大小,一般要設(shè)置的比分區(qū)大,防止有壞塊 vol_type=dynamic?????????#?卷類型,動態(tài)卷 vol_name=rootfs??????????#?卷名,rootfs vol_flags=autoresize?????#?自動大小
?
審核編輯:湯梓紅
評論
查看更多