Hi!大家好,我是CrazyCatJack。又和大家見面了。今天給大家帶來的是構建Linux下的根文件系統。希望大家看過之後都能構建出符合自己需求的根文件系統^_^ 1.內容概述 1.構造過程 今天給大家展示的根文件系統構造過程如下圖所示: 正如大家看到的,這是一個環環相扣的過程。因為在這四個方面的 ...
Hi!大家好,我是CrazyCatJack。又和大家見面了。今天給大家帶來的是構建Linux下的根文件系統。希望大家看過之後都能構建出符合自己需求的根文件系統^_^
1.內容概述
1.構造過程
今天給大家展示的根文件系統構造過程如下圖所示:
正如大家看到的,這是一個環環相扣的過程。因為在這四個方面的內容其實相互包含,有很多交集的地方,所以我用環圖給大家展示。在第一部分,我會給大家講解如何在etc/目錄下編寫相應的配置文件,包含etc/init.d/rcS和etc/fstab等;在第二部分,將會教大家使用mdev,利用它來添加熱插拔功能,自動創建已經存在和即將加入的設備驅動節點;第三部分將給大家詳細講解如何用工具生成兩種文件類型的根文件系統,包含yaffs2和jffs2類型;第四部分給大家講解如何用NFS掛載根文件系統,包含啟動後掛載和啟動前掛載兩種方法。
2.最小根文件系統
今天我們構建的最小根文件系統啟動過程如下:
這是我做的最小根文件系統的執行流程圖。這其中2.3.4步是busybox的工作。關於busybox請參照我的上一篇博文《Linux根文件系統分析之init和busybox》,裡面CCJ給大家詳細講解了2.3.4步的內容^_^ 。今天主要給大家講解第一步和第五步。
1) 創建設備console和null:
首先,我們需要創建一個目錄,自己命名。這裡博主創建CCJ目錄:mkdir CCJ。然後進入自己創建的這個文件夾目錄,並創建dev目錄:mkdir dev 。進入目錄dev:cd dev/ 。然後我們需要查看一下console和null的主次設備號:ls /dev/console /dev/null -l 。這裡博主顯示的console的主設備號為5,次設備號為1;null的主設備號為1,次設備號為3。現在我們就可以創建設備console和null了:
mknod console c 5 1
mknod null c 1 3
在CCJ目錄下創建etc目錄:mkdir etc 。創建etc目錄下的inittab配置文件:vi etc/inittab 。併在其中添加console::askfirst:-/bin/sh 使這個shell的標準輸入,標準輸出,標準錯誤都指向這個console。第一步就這樣輕鬆的完成啦!
2)配置C庫:
首先我們創建lib目錄,這個目錄將用來存放C庫的文件:mkdir CCJ/lib 。進入你存放C庫文件的目錄下,將C庫文件複製到CCJ/lib目錄下:cp *.so* /CCJ/lib -d。這裡CCJ將C庫中的動態庫文件及其鏈接關係都複製到了CCJ/lib目錄下。這樣配置C庫也完成了。
2.構造過程
1.編寫etc目錄下的配置文件和mdev的使用
由於使用mdev同樣要配置etc目錄下的配置文件,所以CCJ將這兩個過程合併為一個小題目一起給大家講解^_^ 。
其實經過上面的過程,我們解決了根文件系統執行的第一步到第五步,現在已經可以生成一個小小的根文件系統了。但如果你生成並燒寫到硬體上就會發現,這個小小的根文件系統的確能夠正常運行,但它的功能還很有限。為了讓它有更加豐富的功能和更方便的使用,現在我們需要添加一些新的配置。
此刻我們製作的根文件系統中有些程式還沒有安裝,比如ps程式。有兩種方法,一種是在根文件系統啟動後我們手動掛載proc:
mkdir proc
mount -t proc none /proc
這裡的proc是linux內核提供的虛擬文件系統。它會將linux系統運行時的信息採集,必須將它掛接到/proc目錄下。我們才能使用ps程式。那麼經過這樣的掛載我們就可以正常使用ps了。下麵是在燒寫了根文件系統的硬體上執行的命令:
ps # ps PID Uid VSZ Stat Command 1 0 3088 S init 2 0 SW< [kthreadd] 3 0 SWN [ksoftirqd/0] 4 0 SW< [watchdog/0] 5 0 SW< [events/0] 6 0 SW< [khelper] 55 0 SW< [kblockd/0] 56 0 SW< [ksuspend_usbd] 59 0 SW< [khubd] 61 0 SW< [kseriod] 73 0 SW [pdflush] 74 0 SW [pdflush] 75 0 SW< [kswapd0] 76 0 SW< [aio/0] 710 0 SW< [mtdblockd] 745 0 SW< [kmmcd] 763 0 3092 S -sh 770 0 3092 R ps
這裡我們可以看到有許多進程,其中PID表示的是進程號。ps是用來查看後臺進程工作情況的命令。這時,我們進入proc目錄,隨便打開一個進程查看:
# cd /proc/ # ls 1 745 diskstats locks sys 2 75 driver meminfo sysrq-trigger 3 76 execdomains misc sysvipc 4 763 fb modules timer_list 5 771 filesystems mounts tty 55 asound fs mtd uptime 56 buddyinfo interrupts net version 59 bus iomem partitions vmstat 6 cmdline ioports scsi yaffs 61 cpu irq self zoneinfo 710 cpuinfo kallsyms slabinfo 73 crypto kmsg stat 74 devices loadavg swaps # cd 1 # ls -l fd lrwx------ 1 0 0 64 Jan 1 00:10 0 -> /dev/console lrwx------ 1 0 0 64 Jan 1 00:10 1 -> /dev/console lrwx------ 1 0 0 64 Jan 1 00:10 2 -> /dev/console
正如大家看到的,proc/目錄下有許多的進程。首列數字與上面的PID號對應,進入PID號,既是進入對應的應用程式。通過" ls -l fd "發現PID為1的進程其標準輸入,標準輸出,標準錯誤都指向/dev/console。
這種掛載虛擬文件系統的方法雖然可用,但是十分麻煩,如果不想自己一個一個手動掛載的話,可以在etc/下編寫配置文件,統一處理。這樣在根文件系統啟動的時候,配置文件會幫我們處理好所有程式的文件系統掛載。我們就能直接使用各種程式了^_^ 。
在etc/inittab中添加::sysinit:/etc/init.d/rcS 。然後創建rcS這個腳本文件:mkdir etc/init.d vi etc/init.d/rcS。在其中輸入:mount -t proc none /proc。保存後再給它添加可執行許可權:chmod +x etc/init.d/rcS 。這樣修改後的根文件系統就會在啟動時為應用程式自動掛載proc,效果和上面手動掛載的一樣。這裡我們也可以在rcS文件中添加:mount -a 命令來取代mount -t 命令。mount -a命令是根據etc/fstab來掛載文件的。編寫etc/fstab為:proc /proc proc defaults 0 0。其效果和上面相同。
由於linux下有很多設備驅動,如果手動一個一個添加dev/目錄下的內容十分麻煩,所以我們可以用udev自動添加設備節點。這裡我們用到的是busybox下的udev的簡化版:mdev。那麼我們該如何配置才能使用mdev呢?查看busybox目錄下的mdev.txt文件,裡面有詳細的說明:
Mdev has two primary uses: initial population and dynamic updates. Both require sysfs support in the kernel and have it mounted at /sys. For dynamic updates, you also need to have hotplugging enabled in your kernel. Here's a typical code snippet from the init script: [1] mount -t sysfs sysfs /sys [2] echo /bin/mdev > /proc/sys/kernel/hotplug [3] mdev -s Of course, a more "full" setup would entail executing this before the previous code snippet: [4] mount -t tmpfs mdev /dev [5] mkdir /dev/pts [6] mount -t devpts devpts /dev/pts
首先,根據 [1]、[4]我們得知,需要sys目錄,dev目錄。且需要添加sysfs和tempfs文件類型。所以在etc/fstab中添加:
sysfs /sys sysfs defaults 0 0
tmpfs /dev tmpfs defaults 0 0
這裡從左至右依次代表:設備名、掛載點、文件系統類型、預設參數等。又根據[2]、[3]、[5]、[6]在etc/init.d/rcS中添加:
mkdir /dev/pts
mount -t devpts devpts /dev/pts
echo /sbin/mdev > /proc/sys/kernel/hotplug
mdev -s
這裡的hotplug表熱拔插,指向mdev。當添加新設備時,會調用它來創建新設備節點。而mdev -s則表示把現有的設備節點創建出來。經過這一番更改,我們重新生成根文件系統,燒寫到硬體設備上,通過終端觀察實驗現象:
大家可以看到dev/目錄下有很多設備節點,這都是mdev自動創建出來的。etc目錄下配置文件和mdev使用講解完畢。
2.生成yaffs2和jffs2文件
下麵講一下如何利用工具生成yaffs2和jffs2文件。因為我們在linux下構建的根文件系統是要燒寫到硬體平臺上的,所以需要生成一個可燒寫的文件。今天將兩種可燒寫的根文件系統的文件類型:yaffs2和jffs2。
1>yaffs2:
首先我們需要從網路或其他途徑獲取到mkyaffs2image工具,利用它來生成yaffs2文件。進入存有mkyaffs2image工具的目錄下。將它解壓縮:
cd document_mkyaffs2/
tar xjf yaffs_source_util_larger_small_page_nand.tar.bz2
cd Development_util_ok
cd yaffs2/
cd utils/
進入工具目錄後:make 。生成我們需要的mkyaffs2image。將它複製:cp mkyaffs2image /usr/local/bin/。並給它可執行許可權:chmod +x /usr/local/bin/mkyaffs2image。再次進入我們的CCJ目錄,利用mkyaffs2image生成可燒寫的根文件系統:mkyaffs2image CCJ CCJ.yaffs2。
2>jffs2:
生成jffs2比yaffs2要稍稍複雜一些。CCJ這裡用到的是"mtd-utils-05.07.23.tar.bz2",它是MTD設備的工具包,編譯它就會生成製作jffs2的工具。它需要zlib壓縮包,所以我們要先安裝zlib。大家可以自行下載zlib的源碼進行安裝,這裡舉例說明:
tar xzf zlib-1.2.3.tar.gz
cd zlib-1.2.3/
./configure --shared --prefix=/usr/
make
這裡的shared是編譯動態庫,prefix表示將zlib安裝在哪裡。make生成zlib後,make install進行安裝。
現在有了zlib後,我們可以編譯jffs2的生成工具了。
tar xjf mtd-utils-05.07.23.tar.bz2
cd mtd-util-05.07.23/util
make
make install
現在我們就安裝瞭解壓後的jffs2生成工具。進入CCJ目錄,執行:mkfs.jffs2 -n -s 2048 -e 128KiB -d CCJ -o CCJ.jffs2
這裡的-n表示不要在每一個擦除塊上加上清楚標誌;-s 2048表示一頁大小為2048位元組;-e 128KiB表示一個擦除塊大小為128KB;-d 表根文件系統目錄;-o表示輸出文件。按理說,執行完這步生成的jffs2燒寫到硬體平臺上就能夠正常運行,但是請大家註意更改自己的bootloader的環境變數,更改為掛載jffs文件類型,而不要預設為yaffs,否則會啟動失敗。
3.NFS掛載根文件系統
這裡也給大家介紹兩種掛載方法:1.是在已經啟動的硬體平臺上,將伺服器根文件系統掛載到硬體平臺上。2.是在未啟動的硬體平臺上,通過修改環境變數,指定掛載地址為伺服器地址,系統一啟動就掛載伺服器的根文件系統。
1>啟動後掛載:
要想用NFS掛載根文件系統,必須滿足兩個條件:(1)伺服器允許那個目錄可被掛接。(2)硬體平臺去掛接那個目錄。首先是第一個條件,我們需要到etc/exports里去配置被允許掛接的目錄:
cd CCJ
vi /etc/exports
在其中添加我們根文件系統所在目錄:
保存後,重啟NFS服務:/etc/init.d/nfs-kernel-server restart。理論上現在就可以掛載了,我們可以先試驗一下,用伺服器掛載自己的根文件系統看能否成功:
mount -t nfs 192.168.1.19:/work/nfs_root/CCJ /mnt
如果系統沒有提示出錯,而且根文件系統能夠正常使用,就說明我們成功了。那麼現在來真正的掛載,在已經啟動的硬體平臺的終端上,我們創建掛載點:mkdir /mnt。然後開始掛載:
mount -t nfs -o nolock 192.168.1.19:/work/nfs_root/CCJ /mnt
此時,如果掛載成功,在硬體平臺上顯示的就是伺服器的根文件系統了,裡面的文件內容一模一樣,在伺服器上對文件內容的更改也會顯示在硬體平臺上^_^ 。
2>啟動前掛載:
這裡,CCJ使用的bootloader是u-boot。只需在系統啟動時,進入u-boot。修改u-boot的環境變數,使系統的根文件系統地址指向伺服器的地址即可。在u-boot下,NFS掛載的定義格式如下:
nfsroot=[<server-ip>:]<root-dir>[,<nfs-options>]
ip=<client-ip>:<server-ip>:<gw-ip>:<netmask>:<hostname>:<device>:<autoconf>
所以我們只需根據自己實際的IP地址、網關、子網掩碼等替換掉其中的參數,然後將這條命令輸給u-boot並保存就可以了。這裡CCJ的硬體平臺IP=192.168.1.13;伺服器IP=192.168.1.19;網關=192.168.1.1;子網掩碼=255.255.255.0 。在u-boot下,輸入print就可以看到當前的環境變數,其中和掛載根文件系統相關的是bootargs:
bootargs=noinitrd root=/dev/mtdblock3 rootfstype=jffs2 init=/linuxrc console=ttySAC0
現在根據掛載跟文件系統的格式,我們需要更改:
set bootargs noinitrd root=/dev/nfs nfsroot=192.168.1.19:/work/nfs_root/CCJ ip=192.168.1.13:192.168.1.19:192.168.1.1:255.255.255.0::eth0:off rootfstype=jffs2 init=/linuxrc console=ttySAC0
將這條環境變數保存,然後啟動內核。就可以看到我們的根文件系統和伺服器是一樣的,也就是說掛載到了伺服器的根文件系統上 。
敬告: 本文原創,歡迎轉載^_^ 轉載請在文章醒目處註明: 原創作者ID: CrazyCatJack |
題外話:
馬上就是2017年了,首先祝大家元旦快樂!^_^ 這一年裡,CCJ收穫了很多。完成了為期一年的項目,做出了滿意的機器人;找到了心儀的工作,馬上就要到廣東去做linux驅動開發了,從來沒有到過這麼往南的地方呢;相信大家也收穫良多吧,祝我們新的一年有更多的成長,世界也會因代碼而不一樣吧,嘿嘿~
CrazyCatJack
2016-12-31 16:06:18