Linux之搭建自己的根文件系統


  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

原始博文鏈接:http://www.cnblogs.com/CrazyCatJack/p/6238385.html                       

 

題外話:

  馬上就是2017年了,首先祝大家元旦快樂!^_^ 這一年里,CCJ收獲了很多。完成了為期一年的項目,做出了滿意的機器人;找到了心儀的工作,馬上就要到廣東去做linux驅動開發了,從來沒有到過這么往南的地方呢;相信大家也收獲良多吧,祝我們新的一年有更多的成長,世界也會因代碼而不一樣吧,嘿嘿~

 

 

 

 

 

CrazyCatJack

2016-12-31 16:06:18

 

 

 

 

 

 

 

 

 

 

  

 

 

 

 

 

 


免責聲明!

本站轉載的文章為個人學習借鑒使用,本站對版權不負任何法律責任。如果侵犯了您的隱私權益,請聯系本站郵箱yoyou2525@163.com刪除。



 
粵ICP備18138465號   © 2018-2025 CODEPRJ.COM