BusyBox製作根文件系統

文件系統的特點:
    Linux系統將磁盤、flash等存儲設備劃分爲若干個分區,在不同的分區存放不同類別的文件,與Windows的C盤類似,Linux一樣要在一個分區上存放系統啓動所必須的文件,比如內核映像文件(在嵌入式系統中,內核一般單獨存放在一個分區中)、內核啓動後運行的第一個程序(init)、給應用戶提供操作界面的shell程序、應用程序所依賴的庫等。這些必須的、基本的文件合稱爲根文件系統,他們存放在一個分區中。Linux系統啓動後首先掛接這個分區,稱爲掛接(mount)根文件系統。其他分區上所有的目錄、文件的集合,也稱爲文件系統。
   Linux以樹狀結構管理所有目錄,文件,其他分區掛接在某個目錄上,這個目錄被稱爲掛接點或安裝點,然後就可以通過這個目錄來訪問這個分區上的文件了。比如根文件系統被掛接在根目錄"/"上後,在根目錄下就有根文件系統的各個目錄、文件:/bin、/sbin、/mnt 等;再將其他分區掛接到/mnt目錄上,/mnt目錄下就有這個分區的各個目錄、文件。

      在一個分區上存儲文件時,需要遵循一定的格式,這種格式稱爲文件系統類型,比如ntfs,ext2,yaffs等。除這些擁有實實在在的存儲分區的文件系統類型外,Linux還有幾種虛擬的文件系統類型,比如proc、sysfs等,他們的文件並不存儲在實際的設備上,而是在訪問他們是由內核臨時生成。

根文件系統目錄結構:
1、/bin 目錄:
    該目錄下存放所有用戶都可以使用的、基本的命令。這些命令在掛接其他文件系統之前就可以使用。
2、/sbin目錄:
    該目錄下存放系統命令,即只有管理員才能使用的命令,系統命令還可以存放在/usr/sbin、/usr/local/sbin 目錄下。/sbin目錄找那個存放的是基本的系統命令,他們用於啓動系統,修復系統等,也是在掛接其他文件系統之前就可以使用/sbin。不是急需使用的系統命令存放在/usr/bin目錄下,本地安裝的系統命令存放在/usr/local/sbin目錄下。
3、/dev目錄:
    存放設備文件,可以使用udev機制維護這個目錄。
4、/etc目錄:
    存放各種配置文件,其下的目錄和文件都是可選的,他們依賴於系統中所擁有的應用程序,依賴於這些程序是否需要配置文件。
5、/lib目錄:
    存放共享庫和可加載模塊(即驅動程序),共享庫用於啓動系統、運行根文件系統中的可執行程序,比如/bin、/sbin目錄下的程序。其他不適根文件系統所必須的庫文件可以放在其他目錄,比如/usr/lib、/var/lib等。
6、/home目錄:用戶目錄,在/home目錄下都有一個普通用戶名命名的子目錄,存放用戶相關的配置文件。
7、/root目錄:
8、/usr目錄:
9、/var目錄:
10、/proc目錄:
    這是一個空目錄,常作爲proc文件系統的掛接點,proc文件系統是個虛擬的文件系統,它沒有實際的存儲設備,裏面的目錄、文件都是由內核臨時生成的,用來表示系統的運行狀態,也可以操作其中的文件控制系統。系統啓動後,使用以下命令掛接proc文件系統(通常在/etc/fstab進行設置以自動掛接)。
mount -t proc none /proc
11、/mnt目錄:
12、/tmp目錄:

    一些需要生產臨時文件的程序要用到/tmp目錄,所以/tmp目錄必須存在,並且可以訪問。

init進程介紹及用戶程序啓動過程:
    init進程是由內核啓動的第一個(也是唯一的一個)用戶進程(進程ID爲1),它根據配置文件決定啓動哪些程序,比如執行某些腳本、啓動shell、運行用戶指定的程序等。init進程是後續所有進程的發起者,比如init進程啓動/bin/sh程序後,才能夠在控制檯上輸入各種命令。

    init進程的執行程序通常是/sbin/init,上面講述的init進程的作用只不過是/sbin/init這個程序的功能。我們完全可以編寫自己的/sbin/init程序,或者傳入命令行參數"init =xxx"指定某個程序作爲init程序運行。 通常使用busybox集成的init程序。

busybox init進程的啓動子進程:(其源代碼在init/init.c文件中)。
    如果存在/etc/inittab文件,busybox init 程序解析它,然後按照他的指示創建各種子進程,否則使用默認的配置創建子進程。
    /etc/inittab 文件中每個條目用來定義一個子進程,並確定他的啓動方法,格式如下:
<id>:<runlevels>:<action>:<process>
    對於busybox init進程,上述各個字段作用如下:
1、<id>:表示這個進程要使用的控制檯(即標準輸入輸出錯誤設備)。如果省略,則使用與init進程一樣的控制檯。
2、<runlevles>:對於busybox init程序,這個字段沒有意義,可以省略。
3、<action>:表示init進程如何控制這個子進程,有8中取值(執行時機)。
sysinit 系統啓動後最先執行
wait 執行完sysinit類進程後執行
once
respawn
askfirst
shutdown
restart
4、<process>:要執行的程序,它可以是可執行程序,也可以是腳本。如果<procsee>字段前有"-"字符,這個程序被稱爲“交互的”。
   
     在/etc/inittab 文件的控制下,init進程的行爲總結如下:
 a、在系統啓動前期,init進程首先啓動<action>爲sysinit、wait、once的3類子進程。
 b、在系統正常運行期間,init進程首先啓動<action>爲respawn、askfirst的兩類子進程。
 c、在系統退時,執行<action>爲shutdown、restart、ctlatdel的3類子進程(之一或全部)。
 
     如果根文件系統中沒有/etc/inittab 文件,busybox init程序將使用如下默認的inittab條目:
 ::sysinit:/etc/init.d/rcS
 ::askfirst:/bin/sh
 tty2::askfirst:/bin/sh
 tty3::askfirst:/bin/sh
 tty4::askfirst:/bin/sh
 ::ctrlaltdel:/sbin/reboot
 ::shutdown:/sbin/swapoff -a
 ::shutdown:/bin/umount -a -r
 ::restart:/sbin/init
 
 /etc/inittab實例:
 放在busybox 的exampes/intitab 文件,創建一個inittab,內容如下:
 
 #/etc/inittab
 #這是init進程啓動的第一個子進程,它是一個腳本,可以在裏面指定用戶想執行的操作
 #比如掛接其他文件系統,配置網絡等
 ::sysinit:/etc/init.d/rcS
  #啓動shell,以/dev/ttySAC0作爲控制檯
 ttySAC0::askfirst:-/bin/sh
  #按下Ctrl + Alt +Del 之後執行的程序,不過在串口控制檯中無法輸入 Ctrl + Alt +Del組合鍵
 ::ctrlaltdel:/sbin/reboot
 #重啓、關機前執行的程序

 ::shutdown:/bin/umount -a -r


移植busybox:
    busybox將衆多的UNIX命令集合進一個很小的可執行程序中,其按模塊進行設計,可以很容易地加入、去除某些命令,或增減命令的某些選項。使用busybox創建最小根文件系統時,只需要在/dev目錄下創建必要的設備節點、在/etc目錄下創建一些配置 文件就可以了,如果busybox使用動態連接,還要在/lib目錄下包含庫文件。 
 
編譯、安裝busybox:
一、下載,解壓busybox:
   tar xjf busybox-1.7.0.tar.bz2
   busybox集合了幾百個命令,在一般系統中並不需要全部使用,可以通過配置busybox 來選擇這些命令,定製某些命令的功能(選項)、指定busybox的連接方法(動態鏈接還是靜態鏈接)、指定busybox的安裝路徑。
二、配置busybox,在busybox-1.7.0目錄下執行"make menuconfig"命令即可進入配置界面:
   使用默認配置,執行"make menuconfig"後退出,保存配置即可。
   
   busybox常用配置選項:
   1、busybox的性能微調。
    設置TAB鍵補全:
    Busybox Settings--->
    Busybox Library Tuning --->
    [*] Tab competion
   2、連接/編譯選項。
    指定是否使用靜態連接:
    Build Options --->
    [ ] Build BusyBox as a static binary (no shared libs)
    使用glibs時,如果靜態編譯busybox會提示以下警告信息,表示會出現一些莫名其妙的問題。
    #warning static linking against glibs produces buggy executables
  所以使用動態連接的busybox,在構造根文件系統是需要在/lib目錄下方直glibs庫文件。
   3、Archival Utilities選項。
        選擇tar命令:
    Archival Utilities --->
    [*] tar
   4、Linux Module Utilites選項。
    要使用可加載模塊,Linux Module Utilities下面的配置要選上.
    Linux Module Utilities --->
    [*]
    [*]
    ...
   5、Linux System Utilities 選項。
    支持mdev,這可以很方便的構造/dev目錄,並且可以支持熱拔插設別,另外爲方便調試,選中mount、umount命令,並讓mount命令支持NFS(網絡文件系統)。
    Linux System Utilities --->
    [*] mdev
    [*] Support /etc/mdev.conf
    [*] Support command execution as device addition/removal
    [*] mount
    [*] Supprot mounting NFS file systems
    [*] umount
    [*] umonut -a option
   
   6、Networing Utilities選項
    增加ifconfig命令:
    Networking Utilities --->
    [*] ifconfig
三、編譯和安裝busybox:
a.修改busybox根目錄的Makefile,使用交叉編譯器:
修改爲:
175 ARCH ?= arm
176 CROSS_COMPILE ?= arm-linux-
b.執行“make”命令編譯busybox。
c.安裝,執行“make CONFIG_PREFIX = dir_name install ,就可以將busybox安裝在dir_name指定的目錄下。
    在安裝目錄下會生成如下文件、目錄:(如安裝目錄/work/nfs_root/fs_mini)
 bin
 linuxrc -> bin/busybox  //(uboot啓動參數就是 init=linuxrc)
 sbin
 usr
    其中Linuxrc和上面分析的/sbin/init程序的功能完全一樣,其他目錄下是各種命令,不過他們都是到/bin/busybox的符號鏈接,比如  安裝目錄下的 sbin 目錄下/work/nfs_root/fs_mini/sbin的命令:
 halt -> ../bin/busybox
 ifconfig -> ../bin/busybox
 ...

    除bin/busybox外,其他文件都是到bin/busybox的符號鏈接。

使用glibc庫:
    參考製作交叉編譯工具鏈,若已製作交叉編譯工具鏈,則已經生成了glibc庫,可以直接使用它來構建根文件系統。
glibc庫的組成:
    glibc庫的位置是/work/tools/gcc-3.4.5-glibc-2.3.6/arm-linux/lib,裏面的目錄,文件可以分爲7類:
 1.加載器ld-2.3.6.so,ld-linux.so.2,動態程序啓動前,他們被用來加載動態庫。
 2.目標文件(.o)。比如crtl.o crti.o等,在生成應用程序時,這些文件像一般的目標文件一樣被連接。
 3.靜態庫文件(.a)。比如靜態數學庫libm.a、靜態C++庫 libstdc++.a等,編譯靜態程序時會連接他們。
 4.動態庫文件(.so、.so.[0-9]*)。他們可能是一個連接文件,編譯動態庫時會用到這些文件,但是不會連接他們,運行時才連接。
 5.libtool庫文件(.la).
 6.ldscripts目錄。裏面是各種連接腳本,在編譯應用程序時,他們被用於指定程序的運行地址、各段的位置等。
 7.其他目錄及文件。
 
安裝glibc庫:
    在開發板上只需啊喲加載器和動態庫,假設要構建的根文件系統目錄爲/work/nfs_root/fs_mini,操作如下:
 $ mkdir -p /work/nfs_root/fs_mini/lib
 $ cd /work/tools/gcc-3.4.5-glibc-2.3.6/arm-linux/lib
 $ cp *.so* /work/nfs_root/fs_mini/lib -d
 
    上面複製的庫文件不是每一個都會被用到,可以根據應用程序對庫的依賴關係保留要用到的,可以通過ldd命令查看一個程序會用到哪些庫,主機自帶的ldd命令不能查看價差編譯出來的程序,有一下兩種代替的方法:
 1、如果有uClibc-0.9.28的代碼,可以進入utils子目錄生成ldd.host工具。
 $ cd uClibc-0.9.28/utils
 $ make ldd.host
然後將生成的ldd.host放到主機/usr/local/bin目錄下即可使用。比如對於動態連接的Uusybox,他的庫依賴關係如下:
 $ ldd.host busybox
  libcrypt.so.1 => /lib/libcrypt.so.1 (0x00000000)
  libm.so.6 => /lib/libm.so.6 (0x00000000)
  libc.so.6 => /lib/libc.so.6 (0x00000000)
  /lib/ld-linux.so.2 => /lib/ld-linux.so.2 (0x00000000)
折表示busybox要使用的庫文件有libcrypt.so.1 、libm.so.6 、libc.so.6,加載器爲/lib/ld-linux.so.2,主機上沒有對應的文件沒關係,開發板的根文件系統上有就行。
 2、可以使用下面的命令:
 $ arm-linux-readelf -a "your binary" | grep "Shared",
 比如對於動態連接的busybox:

 $ arm-linux-readelf -a ./busybox | grep "Shared"(與上面相比,少了加載器,但要依賴加載器)

構建根文件系統:

    上面兩節介紹了編譯安裝busybox、C庫,建立了bin/, sbin/, sur/bin/ ,sur/sbin/, linuxrc,lib/等目錄 (busybox安裝完的時候就有了bin sbin linuxrc user目錄)。
    接下來介紹餘下目錄的建立。假設開發板根文件系統在主機上的目錄爲/works/nfs_root/fs_mini。
一、構建etc目錄:
    init進程根據/etc/inittab 文件來創建其他子程序,比如調用腳本文件配置IP地址,掛接其他文件系統,最後啓動shell等。
   這裏要創建3個文件:etc/inittab, etc/init.d/rcS, etc/fstab
   1.創建etc/inittab文件
   在/work/nfs_root/fs_mini/etc 目錄下創建一個inittab文件,內容如下:
    # /etc/inittab
    ::sysinit:/etc/init.d/rcS
    ttySAC0::askfirst:-/bin/sh
    ::ctrlaltdel:/sbin/reboot
    ::shutdown:/bin/umount -a -r
   2、創建ect/init.d/rcS文件
   這是一個腳本文件,可以在裏面添加想自動執行的命令,以下命令配置IP地址,掛接/etc/fstab指定的文件系統
    #!/bin/sh
    ifconfig eth0 192.168.1.17
    mount -a
   
   第一行表示這是一個腳本文件,運行時使用/bin/sh解析。
   第二行用來配置IP地址。
   第三行掛接/etc/fstab文件指定的所有文件系統。
   要改變這個文件的屬性,使它能夠執行:
    chmod +x etc/init.d/rcS
   3、創建etc/fstab文件
   內容如下,表示執行mount -a 命令後將掛接proc tmpfs 文件系統。
    #device mount-point type     options dump fsck     order
    proc /proc proc             defaults 0         0
    tmpfs /tmp tmpfs     defaults 0         0
   
   /etc/fstab 文件被用來定義文件系統的靜態信息,這些信息被用來控制mount 命令的行爲,文件中個字段的意義如下:
   1.device:要掛載的設備
      比如/dev/hda2  /dev/mtdblock1 等設備文件,也可以是其他格式,比如對於proc文件系統,這個字段沒有意義,可以是任 意值;對於NFS文件系統,這個字段爲<host>:<dir>.
   2.mount-point:掛接點
   3.type:文件系統類型。
      比如proc,jffs2,nfs等,也可以是auto,表示自動檢測文件系統類型。
   4.option:掛接參數,以逗號隔開。
   
   /etc/fstab的作用不僅僅是用來控制mount -a 的行爲,即使是一般的mount命令也受它控制,其他常用掛接參數:
   
    參數名 說明 默認值
    auto/noauto 決定執行mount-a時是否自動掛接 auto
    user/nouser user:允許普通用戶掛接 nouser:只允許root用戶掛接       nouser
    exec/noexec 決定是否允許運行所掛接的設備上的程序 exec
    Ro 以只讀方式掛接 --
    rw 以讀寫方式掛接 --
    sync/async 修改文件的時候,是否同步寫入設備中 sync
    defaults rw、suid、dev、exec、auto、nouser、async等的組合 --
   
   5、dump和fsck order:用來決定控制dump、fsck程序的行爲。
   
   //inittab 調用rcS,rcS裏面mount fstab裏面的文件系統,inittab 和fstab的內容都是有固定格式的,rcS是腳本。
二、 構建dev目錄:
 有兩種方法構建dev目錄
 1、靜態創建設備文件。
 從系統的啓動過程可知,涉及的設備文件又:/dev/mtdblock*(MTD塊設備)、/dev/ttySAC*(串口設備)、
  /dev/console、/dev/null,只要建立以下設備就可以啓動系統。
    $ mkdir -p /work/nfs_root/fs_mini/dev
    $ cd /work/nfs_root/fs_mini/dev
    $ sudo mknod console c 5 1 
    $ sudo mknod null c 1 3
    $ sudo mknod ttySAC0 c 204 64 //一般系統中ttySAC0主設備號爲4,但2440 2410中是204
    $ sudo mknod mtdblock0 b 31 0
    $ sudo mknod mtdblock0 b 31 1
    $ sudo mknod mtdblock0 b 31 2
  其他設備文件可以當系統啓動後,使用cat /proc/devices 命令查看內核中註冊了那些設備,然後一一創建相應的設備文件。
  2、使用mdev創建設備文件。
     mdev是udev的簡化版本,它也是通過讀取內核信息來創建設別文件。mdev的用途主要有兩個:初始化/dev目錄、動態更新/dev目錄,和熱拔插。要使用mdev,需要內核支持sysfs文件系統,爲了減少對flash的讀寫,還要支持tmpfs文件系統。先確保
內核已經設置了CONFIG_SYSFS、CONFIG_TMPFS配置項。
   mdev相關命令:
   mount -t tmpfs mdev /dev  //使用內存文件系統,減少對Flash的讀寫
   mkdir /dev/pts //devpts用來支持外部網絡連接(telnet)的虛擬終端
   mount -t devpts devpts /dev/pts
   mount -t sysfs sysfs /sys //mdev通過sysfs文件系統獲得設備信息
   echo /bin/mdev>/proc/sys/kernel/hotplug //設置內核,當有設備拔插時調用/bin/mdev程序
   mdev -s     //在/dev目錄下生產內核支持的所有設備的結點
   
    要在內核啓動時自動運行mdev,需要修改/work/nfs_root/fs_mini中的兩個文件:etc/fstab和etc/init.d/rcS。
    修改etc/fstab添加3個文件系統,使得後面可以自動掛載,即相當自動執行mount -t tmpfs mdev /dev ;
    mount -t devpts devpts /dev/pts;mount -t sysfs sysfs /sys 3條命令。
    添加的內容:
        # device mount-point type options dump fsck order
        tmpfs /tmp tmpfs defaults 0 0
        sysfs /sys sysfs defaults 0 0
        tmpfs /dev tmpfs defaults 0 0
    修改etc/init.d/rcS,加入下面幾行,以自動運行他們:
        mount -a
        mkdir /dev/pts
        mount -t devpts devpts /dev/pts
        echo /sbin/mdev > /proc/sys/kernel/hotplug
        mdev -s
    在使用mdev構造dev目錄之前,還要建立兩個設備文件:dev/console、/dev/null。
    
    構建其他目錄:
    其他目錄可以是空目錄,比如proc、mnt、tmp、sys、root等,創建他們。
    
    這樣一個小小的根文件系統就建立好了,開發板可以通過NFS掛接到這裏來作爲根文件系統啓動。如果不想掛接,可以利用這個根文件系統和製作映像文件的工具(如mkyaffsimage)製作一個映像文件,燒寫到開發板,作爲開發板的根文件系統。

 
發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章