Hi!你們好,我是CrazyCatJack。又和你們見面了。今天給你們帶來的是構建Linux下的根文件系統。但願你們看過以後都能構建出符合本身需求的根文件系統^_^html
1.內容概述linux
1.構造過程shell
今天給你們展現的根文件系統構造過程以下圖所示:服務器
正如你們看到的,這是一個環環相扣的過程。由於在這四個方面的內容其實相互包含,有不少交集的地方,因此我用環圖給你們展現。在第一部分,我會給你們講解如何在etc/目錄下編寫相應的配置文件,包含etc/init.d/rcS和etc/fstab等;在第二部分,將會教你們使用mdev,利用它來添加熱插拔功能,自動建立已經存在和即將加入的設備驅動節點;第三部分將給你們詳細講解如何用工具生成兩種文件類型的根文件系統,包含yaffs2和jffs2類型;第四部分給你們講解如何用NFS掛載根文件系統,包含啓動後掛載和啓動前掛載兩種方法。網絡
2.最小根文件系統dom
今天咱們構建的最小根文件系統啓動過程以下:工具
這是我作的最小根文件系統的執行流程圖。這其中2.3.4步是busybox的工做。關於busybox請參照個人上一篇博文《Linux根文件系統分析之init和busybox》,裏面CCJ給你們詳細講解了2.3.4步的內容^_^ 。今天主要給你們講解第一步和第五步。ui
1) 建立設備console和null:this
首先,咱們須要建立一個目錄,本身命名。這裏博主建立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了:spa
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