原文地址:使用busybox構建linux根文件系統 作者:charles413
主機:Windows 7旗艦版,VMware7.1.2,Fedora9
編譯環境:arm-linux-gcc 4.4.3
Linux版本:linux-2.6.32.2
busybox版本:busybox-1.19.4
busybox源碼下載地址:http://www.busybox.net/downloads/
參考資料:《嵌入式Linux應用開發完全手冊》 韋東山
所謂創建根文件系統,就是創建各種目錄,並且在裏面創建各種文件。比如在/bin、/sbin目錄下存放各種可執行程序,在/etc目錄下存放配置文件,在/lib目錄下存放庫文件。Busybox主要用來創建/bin、/sbin等目錄下的可執行文件,如命令行下經常使用的命令ls、mv、cp等。
編譯busybox
Busybox的編譯較爲簡單,一般使用默認配置即可,如果熟悉配置選項的話也可以執行make menuconfig進行手動裁剪。具體配置說明可參考《嵌入式Linux應用開發完全手冊》。
修改busybox頂層目錄的Makefile文件,修改如下兩行:
ARCH ?= arm
CROSS_COMPILE ?= arm-linux
然後執行make,編譯busybox。編譯完成後執行:
make CONFIG_PREFIX=/home/nfs/rootfs install
將busybox安裝到目錄/home/nfs/rootfs下。/home/nfs/rootfs是目標板文件系統的根目錄。執行命令查看安裝busybox後生成的文件:
# ls -l /home/nfs/rootfs/
drwxr-xr-x 2 root root 4096 2012-04-05 15:24 bin
lrwxrwxrwx 1 root root 11 2012-03-31 08:17 linuxrc -> bin/busybox
drwxr-xr-x 2 root root 4096 2012-03-31 08:17 sbin
drwxr-xr-x 5 root root 4096 2012-04-03 07:25 usr
linuxrc是內核啓動的init進程,那內核又如何知道要啓動的init進程是哪個呢?它是由uboot傳遞給linux內核參數中"init=xxx"決定的。在我的目標板的uboot中傳遞給內核的參數爲"init=/linuxrc"。內核如何啓動init進程可以查看內核代碼init/main.c中的init_post函數。
構建lib庫
雖然通過編譯busybox生成了我們需要的可執行文件,但現在在目標板上仍然無法運行,需要添加lib庫來支持可執行文件運行。可以使用uclibc和glibc來構建lib庫。由於編譯lib庫相對複雜,而我們又有現成的lib庫可以使用,這裏我們就實行拿來主義。現成的lib庫就在我們的交叉編譯工具arm-linux-gcc的目錄下,在本人主機上的絕對路徑爲/opt/FriendlyARM/toolschain/4.4.3/arm-none-linux-gnueabi/lib,
把該lib目錄下的所有文件複製到目標板文件系統lib下,執行命令:
#cp -r /opt/FriendlyARM/toolschain/4.4.3/arm-none-linux-gnueabi/lib /home/nfs/rootfs/lib
PS:注意要加-r選項,把軟鏈接文件原樣複製過來,不加-r會複製軟鏈接的鏈接文件,造成存儲空間的浪費。
構建etc目錄
創建etc/inittab,參照busybox的examples/inittab文件,內容如下:
點擊(此處)摺疊或打開
- # /etc/inittab
- # Boot-time system configuration/initialization script.
- # This is run first except when booting in single-user mode.
- #
- ::sysinit:/etc/init.d/rcS
- # /bin/sh invocations on selected ttys
- #
- # Note below that we prefix the shell commands with a "-" to indicate to the
- # shell that it is supposed to be a login shell. Normally this is handled by
- # login, but since we are bypassing login in this case, BusyBox lets you do
- # this yourself...
- #
- # Start an "askfirst" shell on the console (whatever that may be)
- console::askfirst:-/bin/sh
- #tty1::askfirst:-/bin/sh
- # Stuff to do before rebooting
- ::ctrlaltdel:/sbin/reboot
- ::shutdown:/bin/umount -a -r
PS:這裏的console是在構建/dev目錄時創建的設備節點,對應的設備是啓動Linux內核前傳入的命令行參數“console=xxx”指定的控制檯,我傳遞的參數爲“console=ttySAC0,115200”,表示使用串口0,波特率爲115200。
創建etc/init.d/rcS文件。rcS是系統啓動後執行的第一個腳本文件,如果想把自己編寫的應用程序設置爲開機啓動,在本文件中中加入運行該程序的命令即可。內容如下:
點擊(此處)摺疊或打開
- #!/bin/sh
- ifconfig eth0 192.168.1.158
- mount -a
修改添加文件可執行權限:#chmod +x etc/init.d/rcS。
創建etc/fstab文件,內容如下:
點擊(此處)摺疊或打開
- #device mount-poin type options dump fsck order
- proc /proc proc defaults 0 0
- tmpfs /tmp tmpfs defaults 0 0
構建dev目錄
這裏使用busybox的mdev創建設備文件,mdev是udev的簡化版本,它也是通過讀取內核信息來創建設備文件。
要使用mdev,需要內核支持sysfs文件系統,爲了減少對Flash的讀寫,還要支持tmpfs文件系統。先確保內核已經設置了CONFIG_SYSFS、CONFIG_TMPFS配置項。
使用mdev的命令如下,請參考它們的註釋以瞭解其作用:
#mount -t tmpfs mdev /dev (使用內存文件系統,減少對Flash的讀寫)
#mkdir /dev/pts (dev/pts用來支持外部網絡連接(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。需要修改etc目錄下的兩個文件:修改etc/fstab來自動掛載文件系統、修改etc/init.d/rcS加入要自動運行的命令。修改後的文件如下:
etc/fstab
點擊(此處)摺疊或打開
- #device mount-poin type options dump fsck order
- proc /proc proc defaults 0 0
- tmpfs /tmp tmpfs defaults 0 0
- sysfs /sys sysfs defaults 0 0
- tmpfs /dev tmpfs defaults 0 0
etc/init.d/rcS
點擊(此處)摺疊或打開
- #!/bin/sh
- ifconfig eth0 192.168.1.158
- mount -a
- mkdir /dev/pts
- mount -t devpts devpts /dev/pts
- echo /sbin/mdev > /proc/sys/kernel/hotplug
- mdev -s
添加mdev配置文件etc/mdev.conf,mdev.conf可以用來控制設備節點的所有者和權限,格式如下:
<device regex> <uid>:<gid> <octal permissions>
mdev.conf還可以設置mdev在dev目錄下生成的設備節點的名字,Linux內核串口驅動原本對S3C2410、S3C2440註冊的設備名是s3c2410_serial0、s3c2410_serial1、s3c2410_serial2,我們可以修改mdev.conf文件,使mdev在/dev目錄下對應生成ttySAC0, ttySAC1和ttySAC2,以符合應用程序對於串口設備操作的習慣。配置文件mdev.conf的內容如下:
mdev.conf
點擊(此處)摺疊或打開
- # system all-writable devices
- full 0:0 0666
- null 0:0 0666
- ptmx 0:0 0666
- random 0:0 0666
- tty 0:0 0666
- zero 0:0 0666
- # console devices
- tty[0-9]* 0:5 0660
- vc/[0-9]* 0:5 0660
- # serial port devices
- s3c2410_serial0 0:5 0666 =ttySAC0
- s3c2410_serial1 0:5 0666 =ttySAC1
- s3c2410_serial2 0:5 0666 =ttySAC2
- s3c2410_serial3 0:5 0666 =ttySAC3
- # loop devices
- loop[0-9]* 0:0 0660 =loop/
- # i2c devices
- i2c-0 0:0 0666 =i2c/0
- i2c-1 0:0 0666 =i2c/1
- # frame buffer devices
- fb[0-9] 0:0 0666
- # input devices
- mice 0:0 0660 =input/
- mouse.* 0:0 0660 =input/
- event.* 0:0 0660 =input/
- ts.* 0:0 0660 =input/
- # rtc devices
- rtc0 0:0 0644 >rtc
- rtc[1-9] 0:0 0644
- # misc devices
- mmcblk0p1 0:0 0600 =sdcard */etc/rc.d/init.d/sd
- sda1 0:0 0600 =udisk * /etc/rc.d/init.d/udisk
重要的一點忘寫了,希望沒有誤導之前看這篇文章的網友。現補充如下:
由於mdev是通過init進程來啓動的,在使用mdev構造/dev目錄之前,init進程至少要用到兩個設備文件/dev/console、/dev/null,所以要建立這兩個設備文件。
# mkdir -r /home/nfs/rootfs/dev
# cd /home/nfs/rootfs/dev
# mknod console c 5 1
# mknod null c 1 3
構建其他目錄
# mkdir proc mnt tmp sys root
到此,我們的根文件系統構建完畢,/home/nfs/rootfs目錄下就是我們的根文件系統。目標板可以把它通過作爲網絡根文件系統,通過nfs直接啓動。也可以把它製作爲映像文件燒寫到目標板的Flash啓動。