Busybox快速構建根文件系統

1. busybox 下載

  busybox源碼包官網下載     busybox官網開發者手冊

下載完成後,解壓得到如下圖所示目錄:

busybox 與 內核源碼、u-boot源碼配置類似,也存在默認配置,在configs目錄下面,但因爲其配置比較簡單,一般沒采用默認配置.(思考:如何添加自定義的配置到configs目錄使其能make xx_defconfig)

$ make help  //可以查看make 實現哪些功能

2.  編譯busybox

      指定ARCH  、CROSS_COMPILE  、SYSROOT

      示例: 

      $ export  ARCH = powerpc

      $ export CROSS_COMPILE = powerpc-fsl-linux-gnuspe-  

      若 沒設置CROSS_COMPILE變量,則需要在Busybox Settings-->Build Options --> Cross Compiler prefix 填寫 編譯器的前綴

 關於SYSROOT

 CONFIG_SYSROOT:                                                                                                           |  
  |                                                                                                                           |  
  | If you want to build BusyBox with a cross compiler, then you                                                              |  
  | might also need to specify where /usr/include and /usr/lib                                                                |  
  | will be found.                                                                                                            |  
  |                                                                                                                           |  
  | For example, BusyBox can be built against an installed                                                                    |  
  | Android NDK, platform version 9, for ARM ABI with                                                                         |  
  |                                                                                                                           |  
  | CONFIG_SYSROOT=/opt/android-ndk/platforms/android-9/arch-arm                                                              |  
  |                                                                                                                           |  
  | Native builds leave this empty.                                                                                           |  
  |                                                                                                                           |  
  | Symbol: SYSROOT [=]                                                                                                       |  
  | Prompt: Path to sysroot                                                                                                   |  
  |   Defined at Config.in:632                                                                                                |  
  |   Location:                                                                                                               |  
  |     -> Busybox Settings                                                                                                   |  
  |       -> Build Options   

若使用交叉編譯器不設置此選項,則可能出現如下問題

  以上基本配置完成後,make menuconfig 根據需要配置 (一般不用配置)

  需要注意的就幾個點:

  1.BusyBox installation prefix 選項  ,執行make install時安裝的目錄,默認設置爲當前源碼目錄的_install

  2.使用vi風格時 busybox setting->busybox library tuning下的下面兩個開關打開。第一個是選擇vi風格的命令行。

  3. 選中 Build BusyBox as a static binary 可以減少根文件系統空間 ,這樣它自身不需使用動態庫

  4.需要注意Linux Module Utilities 和 Linux System Utilities

  執行make 

執行make install

 

3. Linux踩坑啓動生成的根文件系統

    設置uboot bootargs啓動參數


bootargs=root=/dev/nfs nfsroot=192.168.1.141:/root/rootfs/ 
ip=192.168.16.88:192.168.16.106:192.168.16.1:255.255.255.0::eth1:off 
init=/linuxrc console=ttyS0,115200

 

此時會因爲找不到/etc/init.d/rcS (第一個執行的腳本)  以及終端設備/dev/tty2等設備無法進入命令行

注意時,/etc/inittab是busybox第一個解析的配置文件,當找不到時會使用默認配置,所以當根文件系統缺少/etc/inittab時也不會出現 can't open /etc/inittab的信息。

下面開始一步一步補充根文件系統缺少的文件和目錄

1.創建etc目錄,新建inittab文件

 簡單介紹inittab,詳細後面博客補充

 inittab內容以行爲單位,行與行之間沒有關聯,每行都是一個獨立的配置項,每一個配置項表示一個獨立的意思

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

<id>: id字段與通常的inittab中的含義不同,它代表的是這個語句中process執行所在的tty設備,內容就是/dev目錄中tty設備的文件名。由於是運行process的tty設備的文件名,所以也不能像通常的inittab那樣要求每條語句id的值唯一

<runlevels>: busybox不支持runlevel(沒具體分析過),所以此字段完全被忽略

runlevel也是一個shell變量,並且導出爲環境變量

runlevel變量的作用:Linux操作系統自從開始啓動至啓動完畢需要經歷幾個不同的階段,這幾個階段就叫做runlevel,同樣,當linux操作系統關閉時也要經歷另外幾個不同的runlevel。設置runlevel,是爲了linux系統避免不必要的重啓動。

Linux系統有7個運行級別(runlevel)
運行級別0:系統停機狀態,系統默認運行級別不能設爲0,否則不能正常啓動
運行級別1:單用戶工作狀態,root權限,用於系統維護,禁止遠程登陸
運行級別2:多用戶狀態(沒有NFS)
運行級別3:完全的多用戶狀態(有NFS),登陸後進入控制檯命令行模式
運行級別4:系統未使用,保留
運行級別5:X11控制檯,登陸後進入圖形GUI模式
運行級別6:系統正常關閉並重啓,默認運行級別不能設爲6,否則不能正常啓動

S, s  Single user mode

    runlevel=s,表示將系統設置爲單用戶模式

<action>:sysinit, respawn, askfirst, wait,once, restart, ctrlaltdel, shutdown,initdefault 等(其它參考官網 man inittab介紹)

上面標紅比較常用,需要注意的是:

askfirst,它的含義與respawn相同,只是在運行process前,會打出一句話 "please press Enter to active this console",然後等用戶在終端上敲入回車鍵後才運行process。

sysinit :爲init提供初始化命令行的路徑 <一般在inittab爲si::sysinit:/etc/init.d/rcS 表示執行/etc/int.d目錄下rcS腳本>

si 是系統初始化的進程,該字段可以不寫,當寫si時,實踐中出現了can't open /dev/si: No such file or directory,目前還不太清楚與什麼有聯繫

下面爲成熟的文件系統中的實現:

respawn:每當相應的進程終止執行便重新啓動

wait: 告訴init必須等到相應的進程完成才能繼續執行

shutdown:當系統關機時,執行相應的進程

restart:當init重新啓動時,執行相應的進程。

once:僅執行相應的進程一次,而且不會等待它完成

ctrlaltdel:當按下Ctrl-Alt-Delete組合鍵時,執行相應的進程

#first: run the system script file
#控制檯在啓動之前,執行/etc/init.d/rcS程序
::sysinit:/etc/init.d/rcS
#控制檯啓動時,執行/bin/sh程序。若沒有執行類似登錄,則無法出現交互終端   
::askfirst:-/bin/sh
#按下ctrl+alt+del,執行/bin/reboot程序
::ctrlaltdel:-/bin/reboot
#關機時,執行/bin/umount程序,並傳入兩個參數, -a –r    
::shutdown:/bin/umount -a -r
#重啓,執行/sbin/init程序
::restart:/sbin/init

再次啓動根文件系統會出現can't run '/etc/init.d/rcS': No such file or directory

2.創建rcS文文件,且需要加入執行權限

再次啓動,可以發現能基本出現交互終端

 3.繼續深入的驗證,思考下面問題

 1)如何讓串口終端登錄 以及登錄時密碼與賬戶如何驗證的

     屏蔽/bin/sh ,加入ttyS0:12345:respawn:/sbin/getty -L 115200 ttyS0

     說明:一般情況下上面ttyS0應該只需要寫S0,也就是tty的尾綴,但本文完成最終實驗時,發現啓動時若採用S0還是會出現

      can't open /dev/S0: No such file or directory,待分析成熟文件系統中如何實現的 

#first: run the system script file
#控制檯在啓動之前,執行/etc/init.d/rcS程序
::sysinit:/etc/init.d/rcS

#控制檯啓動時,執行/bin/sh程序。若沒有執行類似登錄,則無法出現交互終端   
#::askfirst:-/bin/sh
ttyS0:12345:respawn:/sbin/getty -L 115200 ttyS0

#按下ctrl+alt+del,執行/bin/reboot程序
::ctrlaltdel:-/bin/reboot

#關機時,執行/bin/umount程序,並傳入兩個參數, -a –r    
::shutdown:/bin/umount -a -r

#重啓,執行/sbin/init程序
::restart:/sbin/init

完成上面後,啓動時,也會出現can't open /dev/ttyS0: No such file or directory,這是因爲系統此時還沒有在/dev 創建對應的設備文件

 2)創建dev目錄後,怎麼讓dev目錄看見對應的設備

    現在系統大部分設備節點都是由mdev或者udev根據驅動實現自動創建的,所以只需要讓腳本執行mdev或者udev相關的操作即可

此時在/etc/init.d/rcS中加入下面內容即可

#!/bin/sh
PATH=/sbin:/bin:/usr/sbin:/usr/bin
runlevel=S
prevlevel=N
umask 022
export PATH runlevel prevlevel

mount -a

echo /sbin/mdev > /proc/sys/kernel/hotplug
mdev -s

/bin/hostname -F /etc/hostname

上面分爲4個部分:

(a)導出壞境變量 

        定義PATH變量,後面用export導出,那PATH就變成了環境變量。

        PATH環境變量是linux系統內部定義的一個環境變量,含義是操作系統去執行程序時會默認到PATH指定的各個目錄下去尋找。如果找不到就認定這個程序不存在,如果找到了就去執行它。將一個可執行程序的目錄導出到PATH,可以讓我們不帶路徑來執行這個程序。

         rcS文件還沒添加,系統啓動就有了PATH的值?原因在於busybox自己用代碼硬編碼爲我們導出了一些環境變量,其中就有PATH。

在busybox的init.c的init_main函數中,有以下幾行代碼,設置了幾個環境變量,其中就有PATH。

/* Make sure environs is set to something sane */

putenv((char *) "HOME=/");

putenv((char *) bb_PATH_root_path);

putenv((char *) "SHELL=/bin/sh");

putenv((char *) "USER=root"); /* needed? why? */

在libbb.h中,有定義bb_PAYH_root_path,其實就是/bin /sbin /usr/bin /usr/sbin

extern const char bb_PATH_root_path[] ALIGN1; /* "PATH=/sbin:/usr/sbin:/bin:/usr/bin" */

(b)掛載根文件系統 mount -a

   mount命令是用來掛載文件系統的。

   mount –a是掛在所有的應該被掛載的文件系統,在busybox中mount –a時busybox會去查找一個文件/etc/fstab文件,這個文件按照一定的格式列出了所有應該被掛載的文件系統(包括了虛擬文件系統)格式統一的

# /etc/fstab: static file system information.
#
# Use 'vol_id --uuid' to print the universally unique identifier for a
# device; this may be used with UUID= as a more robust way to name devices
# that works even if disks are added and removed. See fstab(5).
#
# <file system> <mount point> <type> <options>  <dump>   <pass>
  proc          /proc        proc   defaults     0         0
  sysfs         /sys         sysfs  defaults     0         0
  tmpfs         /var         tmpfs  defaults     0         0
  tmpfs         /tmp         tmpfs  defaults     0         0
  tmpfs         /dev         tmpfs  defaults     0         0

需要注意的是,mdev/udev 需要掛載 tmpfs - /dev   proc-/proc  sysyfs - /sys 不然都無法成功創建設備

編輯完/etc/fstab後,還需手動創建proc  sys  dev 目錄

下面爲沒掛載tmpfs到/dev時,出現的問題

(c) mdev

mdev是udev的嵌入式簡化版本,udev/mdev是用來配合linux驅動工作的一個應用層的軟件,udev/mdev的工作就是配合linux驅動生成相應的/dev目錄下的設備文件。

本來,在dev目錄下,是空目錄。但是當rcS文件中,添加下面兩行,配合上面的文件系統掛載,

echo /sbin/mdev > /proc/sys/kernel/hotplug
mdev -s

在dev目錄下,就會生成很多設備文件。這些設備文件,就是mdev生成的。

配置完成後,串口登錄時出現下面輸入密碼的提示,此時因爲沒有對應/etc/passwd,則無法登錄

關於系統密碼登錄這塊的介紹:

inux的賬號驗證程序是login,login會接收getty傳來的用戶名作爲用戶名參數。
然後login會對用戶名進行分析:如果用戶名不是root,且存在/etc/nologin文件,
login將輸出nologin文件的內容,然後退出。這通常用來系統維護時防止非root用戶登錄。
只有/etc/securetty中登記了的終端才允許root用戶登錄,如果不存在這個文件,則root可以
在任何終端上登錄。/etc/usertty文件用於對用戶作出附加訪問限制,如果不存在這個文件,則沒有其他限制。

在分析完用戶名後,login將搜索/etc/passwd以及/etc/shadow來驗證密碼以及設置賬戶的其它信息,
比如:主目錄是什麼、使用何種shell。如果沒有指定主目錄,將默認爲根目錄;如果沒有指定shell,
將默認爲/bin/bash。

login程序成功後,會向對應的終端在輸出最近一次登錄的信息(在/var/log/lastlog中有記錄)
並檢查用戶是否有新郵件(在/usr/spool/mail/的對應用戶名目錄下)。
然後開始設置各種環境變量:
對於bash來說,系統首先尋找/etc/profile腳本文件,並執行它;然後如果用戶的主目錄中存在.bash_profile文件,
就執行它,在這些文件中又可能調用了其它配置文件,所有的配置文件執行後後,
各種環境變量也設好了,這時會出現大家熟悉的命令行提示符,到此整個啓動過程就結束了。

 創建/etc/passwd文件,添加下面內容即可

root::0:0:root:/home/root:/bin/sh

當我換成root:x:0:0:root:/home/root:/bin/sh時,登錄居然需要密碼,後面待驗證,感覺和busybox vi編輯模式相關

(d)hostname

    hostname是linux中的一個shell命令。命令(hostname xxx)執行後可以用來設置當前系統的主機名爲xxx,直接hostname不加參數可以顯示當前系統的主機名。

    設置了主機名,就可以在命令行中,顯示主機名。

    沒有設置主機名的時候,使用hostname命令,會打印當前的IP地址。

    新建/etc/hostname 且寫入自定義的hostname

3)如何修改根文件系統的提示符

   請參考根文件系統的提示符

 

4. 參考文章

/etc/inittab文件詳解

busybox根文件系統構建

 

 

 

 

 

 

 

 

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