使用busybox制作rootfs


Build Busybox as a static binary(no shared libs),如果選擇上,則busybox將以靜態形式進行編譯,否則將以動態方式編譯。此外,還需要對交叉編譯環境進行配置,選擇其中的Cross Compiler Perfix,輸入交叉編譯器的前綴,我們的嵌入式平台上使用的是arm-uclinux-linu

TAG:  busybox   rootfs  
 
1  獲取源碼解壓
從busybox的官方主頁 http://www.busybox.net ,下載busybox的源碼,目前最新的版本為busybox-1.13.3.tar.bz2
#tar –jvxf busybox-1.13.3.tar.bz2
進入解壓后的busybox源碼目錄
#cd busybox-1.13.3
2  配置busybox
步驟跟編譯linux內核時很像
#make menuconfig
出現一個圖形界面,選擇Busybox Settings,這里可以對編譯、安裝以及調試等模式進行配置。
然后選擇Build Options,對交叉編譯器以及編譯方式進行配置。
其中的第一項是Build Busybox as a static binary(no shared libs),如果選擇上,則busybox將以靜態形式進行編譯,否則將以動態方式編譯。此外,還需要對交叉編譯環境進行配置,選擇其中的Cross Compiler Perfix,輸入交叉編譯器的前綴,我們的 嵌入式平台上使用的是arm-uclinux-linux的交叉編譯工具。
這里我們先選擇靜態編譯,動態方式的稍后再講,注意Build with Large File Support (for accessing files > 2 GB)不要選(默認是選上的),否則編譯后會出現如下錯誤:
miscutils/lib.a(readahead.):In function ‘readahead_main’
readahead.(.text.readahead_main+0×70):undefined reference to ‘readahead’
collect2:ld returned 1 exit status
make :***[busybox_unstripped ]Error 1
 
3         編譯busybox
#make
4         安裝busybox
#make install
可以采用perfix參數安裝到指定目錄下,格式為:make install prefix=xxx目錄,如果不特別指定,將默認在busybox源碼目錄下生成一個_install目錄。到此,busybox基本上可以功成身退 了。我們需要的就是busybox編譯出來的這個_install目錄。
進入_install目錄,可以看到一共有3個目錄和一個文件,分別是:bin、sbin和usr目錄以及linuxrc文件。
在對這幾個目錄進行說明之前,先簡單介紹一下編譯生成的busybox可執行文件,它存在於bin目錄下。Busybox使用了帶參的main 函數:int main(int argc,char *argv[]),在這個定義中,argc是傳遞進來的參數的個數(參數數量),而argv是一個字符串數組,代表從命令行傳遞進來的參數。argv的索 引0是命令行調用的程序名。可以在bin目錄下進行如下操作:
#busybox pwd(注意,busybox這個可執行文件不需要加./)
當為一個可執行程序創建符號鏈接后,在執行這個符號鏈接時,就可以獲取到這個符號鏈接的名字。而busybox正是使用符號鏈接的方式使一個可 執行程序看起來像很多程序一樣。對於busybox中包含的每個工具來講,都會創建一個符號鏈接,這樣就可以使用這些符號鏈接來調用busybox了。然 后busybox接着根據argv[0]的值來調用內部工具。
下面分別對install目錄下的幾個文件進行一些說明。
Ø        bin包含用戶工具,其中,busybox可執行文件就在這個目錄 下,該目錄下其他所有文件都是指向busybox的符號鏈接
Ø        sbin目錄包含操作系統工具,同樣也指向busybox。
Ø        linuxrc是一個鏈接文件,指向busybox。
5         添加etc目錄及基本配置文件
參考一個正常的linux系統將會發現,此時busybox建立的文件系統還缺少很多文件。如果用這個作為文件系統,將是無法運行的。生成這些 配置可以選擇的方法有2種,一種是直接從一個正常運行的系統中拷貝,另一種是借助於busybox的examples。顯然,選擇第二種會容易的多,我們 直接拷貝examples/bootfloopy/etc到install目錄下。
#cp –a ../examples/bootfloppy/etc/ .
然后可以看看etc目錄下的文件,一共有3個目錄和文件,下面逐一對以上幾個文件進行分析和說明。
Ø        inittab文件:系統啟動后訪問的第一個腳本文件,后續啟動的文 件都由它指定。下面看一下busybox中原始的inittab文件內容:
::sysint:/etc/init.d/rcS
::respawn:-/bin/sh
tty2::askfirst:-/bin/sh
::ctrlaltdel:/bin/umount –a -r
其中第一行指定系統的啟動腳本為/etc/init.d/rcS
第二行指定打開一個登錄會話
第三行指定在第三個虛擬終端打開一個無須登錄驗證的shell
第四行指定了當按下ctrl+alt+del組合鍵時的執行命令
Ø        fstab文件:定義了文件系統的各個“掛載點”,需要與實際的系統 相配合。默認的fstab文件內容為:
proc   /proc proc defaults 0 0
其他的根據需要再進行添加,比如devpts  /dev/pts devpts defaults 0 0就是為UNIX PTYs准備的,后面講telnetd時要用到。
Ø        profile文件:終端登陸之后首先運行的腳本。
 
6         添加dev目錄及基本設備文件
調試時要通過串口發送消息到終端顯示。因此串口控制台和終端2個設備文件是必不可少的。
#mkdir dev
#mknod dev/console c 5 1
#mknod dev/ttyAMA0 c 204 64
在啟動參數中,設置console=ttyAMA0
7         添加其他常用目錄
可以選擇home、root、proc、mnt、lib、var、opt、tmp。
此時,一個基本的文件系統的功能就已經完成了。可以采用NFS進行調試。但是,此時你可能會遇到如下問題,系統登錄后終端上會不斷打印:
cannot open /dev/ttyS2:No such file or directory.
原因出在/etc目錄下的inittab文件,我們看一下其內容:
::sysint:/etc/init.d/rcS
::respawn:-/bin/sh
tty2::askfirst:-/bin/sh
::ctrlaltdel:/bin/umount –a -r
這條語句表示在第3個虛擬終端打開一個無須登錄驗證的shell。而我們之前沒有建立這個tty2設備,因此會出錯。解決的辦法有2個:一是屏 蔽該語句,二是建立該設備節點。我們選擇將其屏蔽。
8         相關問題
8.1      使用動態方式編譯 busybox
進入Build Options時,不要選擇Build Busybox as a static binary,其他所有操作步驟跟靜態編譯一樣,你會發現這樣建立的文件系統無法啟動,終端上打印出如下消息:
Kernel panic-not synving:No init found. Try passing init=option to kernel.
為什么會出現這種問題呢?這就得回到兩種編譯方式的特點上來。靜態編譯時是將所用到的庫文件一起編譯了進去,而動態編譯時是在需要時才調用相應 的庫。我們選擇動態編譯后,沒有添加任何庫文件就運行,顯然是會出錯的。那么如何查看busybox可執行文件里使用的庫呢。Readelf這個工具提供 了解決辦法。使用如下命令,參數d表示將文件中所有的動態部分予以顯示。
# arm-uclibc-linux-readelf -d busybox 
Dynamic section at offset 0xca014 contains 18 entries:
  標記        類型                         名稱/值
 0×00000001 (NEEDED)                     共享庫: [libm.so.0]
 0×00000001 (NEEDED)                     共享庫: [libc.so.0]
 0×0000000c (INIT)                       0xbe24
 0×0000000d (FINI)                       0xb2054
 0×00000004 (HASH)                       0×80e8
 0×00000005 (STRTAB)                     0xa500
 0×00000006 (SYMTAB)                     0×8b70
 0×0000000a (STRSZ)                      3259 (bytes)
 0×0000000b (SYMENT)                     16 (bytes)
 0×00000015 (DEBUG)                      0×0
 0×00000003 (PLTGOT)                     0xda0cc
 0×00000002 (PLTRELSZ)                   3040 (bytes)
 0×00000014 (PLTREL)                     REL
 0×00000017 (JMPREL)                     0xb244
 0×00000011 (REL)                        0xb1bc
 0×00000012 (RELSZ)                      136 (bytes)
 0×00000013 (RELENT)                     8 (bytes)
 0×00000000 (NULL)                       0×0
從上面的結果中,我們可以看到,busybox這個程序使用到了libm.so.0和libc.so.0兩個庫文件,實際上這是2個符號鏈接, 分別指向libc-0.9.28.so和libuClibc-0.9.28.so。將以上四個文件分別拷貝到lib目錄下。按理說,這樣應該就可以了,但 是仍然無法正常運行。顯示的錯誤信息和剛剛沒加庫之前一樣。可能的原因有2種:一是庫文件沒有添加全,二是庫文件沒有正確被加載。根據readelf顯示 的結果應該不是第一種原因。那么到底為什么沒被正確加載呢?原來庫文件的加載,還需要一個共享庫加載器。找到對應的文件ld-uClibc- 0.9.28.so和ld-uClibc.so.0添加到lib目錄下后。運行正常。
8.2      終端登錄用戶驗證功 能添加
需要在etc目錄下增加passwd、group和shadow(在編譯busybox時如果不選擇shadow功能將不需要這個文件)3個文 件。
生成這3個文件的方法有:
Ø        手動生成,按照格式規范自己編寫內容;
Ø        通過busybox提供的工具adderuser自動生成
8.2.1        手動方式
首先我們介紹一下如何手動添加。以增加root用戶為例,增加passwd文件,其內容為:
#cat passwd
root:x:0:0:root:/root:/bin/sh
同時,此時要確定root目錄已經存在。
passwd一共由7個字段組成,6個冒號將其隔開。它們的含義分別為:
1     用戶名
2     是否有加密口令,x表示有,不填表示無,采用MD5、DES加密。
3     用戶ID
4     組ID
5     注釋字段
6     登錄目錄
7     所使用的shell程序
增加group文件,其內容為:
#cat group
root:x:0:
Group一共由4個字段組成,3個冒號將其隔開,它們的含義分別為:
1     組名
2     是否有加密口令,同passwd
3     組ID
4     指向各用戶名指針的數組
由於busybox默認啟動了shadow模式,因此需要增加shadow文件,其內容為:
#cat shadow
root:$1$3jZ93Mwq$oaeef6lWIuThavs8wD0Wh1:0:0:99999:7:::
shadow一共由9個字段組成,8個冒號將其隔開,它們的含義分別為:
1     用戶名
2     加密后的口令,若為空,表示該用戶不需要口令即可登陸,若為*號,表示該賬號被禁用。 上面的表示的是123456加密后的口令。
3     從1970年1月1日至口令最近一次被修改的天數
4     口令在多少天內不能被用戶修改
5     口令在多少天后必須被修改(0為沒有修改過)
6     口令過期多少天后用戶賬號被禁止
7     口令在到期多少天內給用戶發出警告
8     口令自1970年1月1日被禁止的天數
9     保留域
這里強調一下shadow文件的由來。/etc/passwd文件對系統的所有用戶都是可讀的,這樣的好處是每個用戶都知道系統上有哪些用戶, 但缺點是其他用戶的口令容易受到攻擊,尤其是當口令較簡單時。所以一些linux系統中使用到了影子口令文件shadow,將用戶的口令存儲在另一個文件 /etc/shadow中,該文件只有根用戶root可讀,大大提高了安全性。
不過,采用這種手動添加文件的方法有一個缺陷,就是如果要為用戶設置登陸口令的話,shadow文件中必須填寫加密后的口令,而這個加密算法我 們又不知道,即使知道,要經過轉換后再添加,比較麻煩。此時,不妨試一下第二種方法。
8.2.2        自動方式
自動生成是使用了busybox提供的adduser工具和passwd工具。
在文件系統正常運行起來后,使用adduser命令,使用方法為:
#adduser root
然后就會在etc目錄下自動生成passwd 、group和shadow3個文件。但是運行該命令后會打印出如下消息:
passwd:unknown uid 0
這表示不能為該用戶設置密碼,此時你會發現要passwd命令也無法使用。
解決的辦法是,打開passwd文件,其內容為:
root:x:1000:1000: Linux User…:/home/root:/bin/sh
將用戶ID和組ID均更改為0
打開group文件,其內容為:
root:x:1000:
同樣將組ID改為0
然后,passwd命令就可以正常使用了。這時為root用戶設置口令:
#passwd root
根據提示輸入密碼。其中,root用戶登陸后的目錄可以手動進行更改。
8.3      telnetd功能 添加
busybox默認已經添加了對telnetd和telnet功能的支持,只需要完成一些相關的設置工作就可以啟動這2個功能了。
Ø          創建/dev/pts目錄
Ø        在/etc/fstab中添加如下信息,掛載devpts文件系統
devpts /dev/pts devpts defaults 0 0
Ø        在/dev目錄下增加ptmx設備文件:
#mknod ptmx c 5 2
Ø        在rcS文件中添加如下腳本,啟動telnetd
if [ -x /usr/sbin/telnetd ] ;
then
        telnetd&
fi
Ø        在/dev目錄下增加null設備文件,否則上述腳本運行時會出錯: 提示找不到null文件。
#mknod null c 1 3
此時,telnetd功能開機就可以啟動了。


免責聲明!

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



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