1. 程式人生 > >根檔案系統製作詳解

根檔案系統製作詳解

什麼是根檔案系統

       linux最頂層的目錄"/"被稱作根目錄,與Windows上的目錄結構有較大的不同。系統中只有一個根目錄,路徑是“/”,而其它的分割槽只是掛載在根目錄中的一個資料夾。系統載入linux核心後,就會掛在一個儲存裝置到根目錄。存在與這個裝置中的檔案系統被稱為根檔案系統。所有的系統命令、系統配置及其他檔案系統的掛載點都位於這個根檔案系統中。

       根檔案系統通常存放於記憶體和 Flash 中,或是基於網路的檔案系統。根檔案系統中存放了嵌入式系統使用的所有應用程式、庫以及其他需要用到的服務。

        根檔案系統頂層目錄結構圖。

       

  通常的linux系統會包含以上目錄,但嵌入式系統中需要精簡化根檔案系統,可忽略下列目錄

.

  

為什麼需要根檔案系統
(1)init程序的應用程式在根檔案系統上
(2)根檔案系統提供了根目錄/
(3)核心啟動後的應用層配置(etc目錄)在根檔案系統上。幾乎可以認為:發行版=核心+rootfs
(4)shell命令程式在根檔案系統上。譬如ls、cd等命令

總結:一套linux體系,只有核心本身是不能工作的,必須要rootfs(上的etc目錄下的配置檔案、/bin /sbin等目錄下的shell命令,還有/lib目錄下的庫檔案等···)相配合才能工作。

根檔案系統的製作過程

      1).通過busybox工具,生成/bin、/sbin、linuxrc、/usr/bin、/usr/sbin.

      2).使用交叉編譯工具鏈,構建/lib目錄.

      3).建立其他空目錄.

      4).配置etc目錄,並初始化/dev目錄.

      5).利用工具製作根檔案系統映像檔案.

製作根檔案系統 
通過使用busybox工具製作幾個重要的檔案,和可執行檔案目錄.

http://www.busybox.net/ 下載busybox原始碼.
tar xjvf busybox-x.x.x.tar.bz2解包
修改Makefile: 

                ARCH   ?=

                CROSS_COMPILE   ?=

                根據自己的開發環境進行配置.  

make menuconfig配置busybox.

        

        Settings部分,主要編譯和安裝busybox的一些選項。這裡主要需要配置:

        1].Build Options -- Build BusyBox as a static binary (no shared libs),表示編譯busybox時,是否靜態連結C庫。我們選擇動態連結C庫。 

        2].Installation Options -- Applets links (as soft-links) -- (X) as soft-links,表示安裝busybox時,將各個命令安裝為指向busybox的軟連結還是硬連結。我們選擇軟連結。

        3].Installation Options -- (/work/nfs_root/fs_mini3) BusyBox installation prefix,表示busybox的安裝位置。我們選擇/work/nfs_root/fs_mini3  

         4].Busybox Library Tuning。保留Command line editing以支援命令列編輯;保留History size以支援記憶歷史命令;選中Tab completion和Username completion以支援命令自動補全   

         Applets部分,他將busybox的支援的幾百個命令分門別類。我們只要在各個門類下選擇想要的命令即可。這裡我們基本保持預設設定。

        1].選中Networking Utilities -- httpd下的Enable -u <user> option,以啟用http伺服器的功能allows the server to run as a specific user 

         5) 編譯安裝 : make ; make install .

          安裝完後在_install就可以看到bin/、sbin/、目錄下的命令了.

    

構建lib/庫

        lib 目錄是存放應用程式所需要的庫檔案,我們還需要根據應用程式需要拷貝相應的庫檔案。

        下面是lib庫的分類:

1].目標檔案,*.o,用於gcc連結可執行檔案.
2].libtool庫檔案(.la),在連結庫檔案時這些檔案會被用到,比如他們列出了當前庫檔案所依賴的其它庫檔案,程式執行時無需這些檔案.
3].gconv目錄,裡面是各種連結指令碼,在編譯應用程式時,他們用於指定程式的執行地址,各段的位置等
4].靜態庫檔案(.a),例如libm.a,libc.a  
5].動態庫檔案 (.so、.so.[0-9]*).  
6].動態連結庫載入器ld-2.3.6.so、ld-linux.so.2  

7].其它目錄及檔案  

        很顯然,第1、2、3、4、7類檔案和目錄是不需要拷貝的。  由於動態連結的應用程式本身並不含有它所呼叫的C庫函式的程式碼,因此執行時需要動態連結庫載入器來為它載入相應的C庫檔案,所以第6類檔案是需要拷貝的。  除此之外,第5類檔案當然要拷貝。但第5類檔案的大小也相當大。

        那有必要全部拷貝嗎,其實,需要哪些庫完全取決於要執行的應用程式使用了哪些庫函式。如果我們只製作最簡單的系統,那麼我們只需要執行busybox這一個應用程式即可

        通過交叉編譯工具readelf可檢視我們的busybox應用依賴了哪些庫檔案.

                       

         可以看到busybox只用到了2個庫,所以我們只需要拷貝這三個庫:通用C庫(libc)、數學庫(libm)、動態連結庫載入器(ld).

         我們將這些庫拷貝進lib/  注意下檔案的符號連結.



配置etc目錄並初始化dev目錄.

         1].init程序簡介:

          init是Linux系統操作中不可缺少的程式之一,它是一個由核心啟動的第一個使用者級程序。
     核心自行啟動(已經被載入記憶體,開始執行,並已初始化所有的裝置驅動程式和資料結構等)之後,就通過啟動一個使用者級程式init的方式,完成引導程序。所以,init始終是第一個程序(其程序編號始終為1)。

          /etc目錄存放的是系統程式的主配置檔案,因此需要哪些配置檔案取決於要執行哪些系統程式,所以我們至少要手工編寫init的主配置檔案inittab。

          系統啟動,Linux的核心被載入之後,機器就把控制權轉交給核心,linux的核心啟動之後,做了一些工作,然後找到根檔案系統裡面的init程式,並執行它,BusyBox的init程序會依次進行以下工作:

·為init設定訊號處理過程

·初始化控制檯

·剖析/etc/inittab檔案

·執行系統初始化命令列,預設情況下會使用/etc/init.d/rcS

·執行所有導致init暫停的inittab命令(動作型別:wait)

·執行所有僅執行一次的inittab(動作型別:once)

    2].inittab指令碼

         inittab檔案中每一行的格式如下所示:(busybox的根目錄下的example資料夾下有詳盡的inittab檔案範例)     

 <id>:<runlevels>:<action>:<process>

     <id>:子程序使用的控制檯(標準輸入、標準輸出、標準錯誤裝置)

     <runlevels>: 1到6,表示不同的六個級別

                  init 0 是停機的意思。也就是說可以用這個命令關機。可以相當於shutdown -P now這個命令,就是用這個命令關機的話,終端不會彈出任何提示訊息,直接就關機了。 
                  init 1 單使用者模式。很多情況下忘了登陸密碼或者root密碼就在單使用者模式下修改。 
                  init 2 多使用者,沒有 NFS。不知道什麼意思,表示沒有用過這個命令。 
                  init 3 完全多使用者模式。這個經常用,就是文字模式~~~ 
                  init 4 未使用,保留。 
                  init 5 圖形介面 
                  init 6 重啟命令。相當於shutdown -r now。

     <action>:init如何控制子程序。

動作說明
sysinit系統啟動後最先執行,  只執行一次,init程序等待它結果才繼續執行其他動作.
wait系統執行完sysinit程序後執行,只執行一次,init程序等待它結束後才繼續執行其他動作 
once系統執行完wait程序後執行,init程序不會等待它結束.
respawn   啟動玩once程序後執行,init程序監測其子程序退出時,重新啟動它.  
askfist啟動完respawn程序後執行, 與respawn類似,不過init程序先輸出"Please press Enter to activate this console".等使用者輸入回車後才啟動子程序.
shutdown     當系統關機或重啟時執行.
restartBusybox中配置了CONFIG_FEATURE_USE_INITTAB,並且init程序接收到SIGUP訊號時執行,現重新讀取,解析/etc/inittab,在重新執行restart程式.
ctrlaltdel當按下ctrl+alt+del組合鍵時執行.


            <process>:可以是要執行的指令碼,也可以是程式。

   3]. inittab樣例
        ::sysinit:/etc/init.d/rcS
        ::respawn:/sbin/getty  115200  tty1
        tty2::askfirst:-/bin/sh
        tty3::askfirst:-/bin/sh
        ::restart:/sbin/init
        ::ctrlaltdel:/bin/umount -a -r

        這個inittab執行下列動作

     ·將/etc/init.d/rcS設定成系統的初始化檔案
     ·在115200 bps的虛擬終端tty1上啟動一個登陸會話 (注意getty的用法)
     ·在虛擬終端tty2和tty3上啟動askfirst動作的shell
     · 如果init重新啟動,將/sbin/init設定成它會執行的程式

     ·告訴init,在系統關機的時候執行umount命令解除安裝所有檔案系統,並且在解除安裝失敗時用只讀模式衝新安裝以保護檔案系統。

rcS指令碼.

       這是一個指令碼檔案,可以在裡面新增想自動執行的命令。下面第三個圖為rcS指令碼 :

      mount -a 自動gua載fstab中的檔案系統,fstab檔案如下.

      

      接著echo列印提示,  最後搜尋啟動目錄init.d/下S[0-9]開頭的服務指令碼. 如 S80network 裡面可以 進行網路配置  ifconfig lo 127.0.0.1.

      

      

初始化dev/目錄

        這個指令碼 寫在我們rcS指令碼啟動的 S00devs 裡面了 ,

        

     工具製作jyafss2映像.

         mkfs.jffs2 -d rootfs -l -e 0x10000 -o rootfs_hi3516a_64k.jffs2 

          -d 目錄  -l  小端模式 , -e 指定擦除塊大小 . -o 輸出映像檔名 .

          最後燒寫完成根檔案系統的製作 .