Linux-2.6.32.2內核在mini2440上的移植----用busybox製作根文件系統

1、交叉編譯Busybox

(1)、解壓 busybox

clx@think:/work$ tar -jxvf busybox-1.20.0.tar.bz2 -C /work/armlinux

(2)、進入源碼,修改Makefile文件:

修改:  
CROSS_COMPILE ?=arm-linux-   //第 164 行  
ARCH ?=arm //第 190 行  

(3)、配置 busybox

clx@think:/work/armlinux/busybox-1.20.0$ make menuconfig

選中[*] Build BusyBox as a static binary (no shared libs) 該選項用於選擇是否使用靜態編譯方式。如果選擇採用靜態編譯,則生成的busybox命令文件在運行時就不需要額外的函數庫支持。爲了簡單起見,這裏建議選擇使用靜態編譯方式。

Busybox Settings  --->Busybox Library Tuning  ---> 保留Command line editing以支持命令行編輯;保留History size以支持記憶歷史命令;選中Tab completion和Username completion以支持命令自動補全的設置採用默認設置

選項Applets,他將busybox的支持的幾百個命令分門別類。我們只要在各個門類下選擇想要的命令即可。這裏我們基本保持默認設置。

(4)、編譯busybox

首先創建一個新的目錄rootfs,作爲整個根文件系統的根目錄

clx@think:/work/armlinux/busybox-1.20.0$ mkdir /work/armlinux/rootfs

編譯 busybox 到rootfs目錄下:

make CONFIG_PREFIX=/work/armlinux/rootfs install

clx@think:/work/armlinux/rootfs$ ls
bin  linuxrc  sbin  usr

安裝完成後,可以看到在rootfs目錄下生成了bin、sbin、usr/bin、usr/sbin目錄以及一個linuxrc鏈接文件,其下包含了我們常用的命令,這些命令都是指向bin/busybox的軟鏈接。

linuxrc是內核啓動的init進程,那內核又如何知道要啓動的init進程是哪個呢?它是由uboot傳遞給linux內核參數中"init=xxx"決定的。在我的目標板的uboot中傳遞給內核的參數爲"init=/linuxrc"。內核如何啓動init進程可以查看內核代碼init/main.c中的init_post函數。

2、構建根文件

嵌入式 Linux 中都需要構建根文件系統,構建根文件系統的規則在 FHS(Filesystem Hierarchy Standard)文檔中,下面是根文件系統頂層目錄。  

目錄   內容 

bin 存放所有用戶都可以使用的、基本的命令。 
sbin   存放的是基本的系統命令,它們用於啓動系統、修復系統等。 
usr   裏面存放的是共享、只讀的程序和數據。 
proc   這是個空目錄,常作爲 proc 文件系統的掛載點。 
dev   該目錄存放設備文件和其它特殊文件。 
etc   存放系統配置文件,包括啓動文件。 
lib   存放共享庫和可加載塊(即驅動程序),共享庫用於啓動系統、運行根文件系統中的可執行程序。
boot   引導加載程序使用的靜態文件 
home   用戶主目錄,包括供服務賬號鎖使用的主目錄,如 FTP 
mnt 用於臨時掛接某個文件系統的掛接點,通常是空目錄。也可以在裏面創建空的子目錄。 
opt 給主機額外安裝軟件所擺放的目錄。 
root root 用戶的主目錄 
tmp   存放臨時文件,通常是空目錄。 
var   存放可變的數據。 

(1)、根據FHS標準依次創建各個子目錄

clx@think:/work/armlinux/rootfs$mkdir root dev etc boot tmp var sys proc lib mnt home
clx@think:/work/armlinux/rootfs$mkdir etc/init.d etc/rc.d etc/sysconfig  
clx@think:/work/armlinux/rootfs$mkdir  usr/lib usr/modules  
clx@think:/work/armlinux/rootfs$mkdir mnt/etc mnt/jffs2 mnt/yaffs mnt/data mnt/temp  
clx@think:/work/armlinux/rootfs$mkdir var/lib var/lock var/run var/tmp  
clx@think:/work/armlinux/rootfs$chmod 1777 tmp  
clx@think:/work/armlinux/rootfs$chmod 1777 var/tmp 

改變了 tmp 目錄的使用權,讓它開啓sticky 位,爲 tmp目錄的使用權開啓此位,可確保tmp目錄底下建立的文件,只有建立它的用戶有權刪除。儘管嵌入式系統多半是單用戶,不過有些嵌入式應用不一定用 root 的權限來執行,因此需要遵照根文件系統權限位的基本規定來設計。 

注意:BusyBox作爲靜態庫編譯,後續自己開發的程序在編譯選後加上 –static 也編譯城靜態,否則程序下載至目標板文件系統上可能報錯:bin/sh: hello :not found,因爲缺少某些必要的庫,爲了方便起見,在這裏將其編譯爲動態鏈接。

選擇上
Busybox Settings  --->
General Configuration  --->
[*] Don't use /usr

選中該項可以避免busybox 被安裝到宿主系統的/usr目錄下,破壞宿主系統

修改:  
CROSS_COMPILE ?=/opt/FriendlyARM/toolschain/4.4.3/bin/arm-linux-   //第 164 行  
make CONFIG_PREFIX=/work/armlinux/rootfs install
clx@think:/work/armlinux/rootfs$ ls
bin  linuxrc  sbin
clx@think:/work/armlinux/rootfs$ mkdir usr 
clx@think:/work/armlinux/rootfs$ mkdir usr/bin usr/lib usr/sbin lib/modules
構建lib庫
雖然通過編譯busybox生成了我們需要的可執行文件,但現在在目標板上仍然無法運行,需要添加lib庫來支持可執行文件運行。可以使用uclibc和glibc來構建lib庫。由於編譯lib庫相對複雜,而我們又有現成的lib庫可以使用,這裏我們就實行拿來主義。現成的lib庫就在我們的交叉編譯工具arm-linux-gcc的目錄下,在本人主機上的絕對路徑爲/opt/FriendlyARM/toolschain/4.4.3/arm-none-linux-gnueabi/lib,

此lib目錄有下面這些東西:
1.目標文件,如crtn.o,用於gcc鏈接可執行文件
2.libtool庫文件(.la),在鏈接庫文件時這些文件會被用到,比如他們列出了當前庫文件所依賴的其它庫文件,程序運行時無需這些文件
3.gconv目錄,裏面是各種鏈接腳本,在編譯應用程序時,他們用於指定程序的運行地址,各段的位置等 (我的4.1.2沒有這個目錄)
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類文件當然要拷貝。 

cp $file-*.so rootfs/lib
cp -d $file.so.[*0-9] rootfs/lib
cp -d ld*.so* rootfs/lib

把該lib目錄下的所有文件複製到目標板文件系統lib下,執行命令:
#cp -f /opt/FriendlyARM/toolschain/4.4.3/arm-none-linux-g
nueabi/lib/ *.so* /work/armlinux/rootfs/lib -a

(2)、構建etc目錄(可將busybox-1.20.0/examples/bootfloppy/etc/下的文件拷貝到etc目錄下

a、創建etc/inittab

init進程根據/etc/inittab文件來創建其他子進程,比如調用腳本文件配置ip地址、掛接其他文件系統,最後啓動shell等。

clx@think:/work/armlinux/rootfs/etc$ cp /work/armlinux/busybox-1.20.0/examples/inittab /work/armlinux/rootfs/etc

修改裏面內容,屏蔽掉不需要的

#etc/inittab  

#制定系統啓動時要執行 rcS 腳本
::sysinit:/etc/init.d/rcS                            
#指定打開一個無需登陸驗證的shell,以s3c2410_serial0爲控制檯 
s3c2410_serial0::askfirst:-/bin/sh    
::ctrlaltdel:/sbin/reboot
::shutdown:/bin/umount -a -r
::shutdown:/sbin/swapoff -a

b、創建etc/init.d/rcS文件

 rcS文件是一個腳本文件,藉助啓動腳本可以設置各種程序開機後自動運行,也可進行其他系統設置,這有點類似於Windows系統中的Autobat自動批處理文件。如果想把自己編寫的應用程序設置爲開機啓動,在本文件中中加入運行該程序的命令即可

#!/bin/sh
echo "Processing /etc/init.d/rcS"
echo "mount -a"
mount -a #mount上fstab文件中所有文件系統
exec /etc/rc.local

使用以下命令改變rcS的執行權限:

clx@think:/work/armlinux/rootfs/etc/init.d$ chmod +x rcS

c、在etc/sysconfig目錄下新建文件HOSTNAME,內容爲”MINI2440”,設置主機名字

d、創建/etc/rc.local 文件

/etc/rc.local是被init.d/rcS 文件調用執行的特殊文件,與Linux 系統硬件平臺相關,如安裝核心模塊、進行網絡配置、運行應用程序、啓動圖形界面等。

#!/bin/sh
echo "Processing /etc/rc.local"
echo "get hostname"
/bin/hostname -F /etc/sysconfig/HOSTNAME

echo "Starting mdev"
echo /sbin/mdev > /proc/sys/kernel/hotplug
mdev -s
echo "ifconfig eth0 192.168.1.250"
ifconfig eth0 192.168.1.250
echo "DeramCatcher"  
echo "Date:2013.5.14" 

clx@think:/work/armlinux/rootfs/etc/init.d$ chmod +x rc.local

e、創建etc/fstab文件

fstab文件描述系統中各種文件系統的信息,應用程序讀取這個文件,然後根據其內容進行自動掛載的工作。創建的代碼如下:

#device    mount-point     type      option     dump   fsck   order 
proc          /proc             proc      defaults     0        0  
none          /tmp            ramfs     defaults     0        0  
sysfs         /sys            sysfs     defaults      0        0  
mdev         /dev             ramfs     defaults      0        0

文件中各字段的意義如下:1)device:要掛接的設備,如/dev/mtdblockl;2)mount-point:掛接點;3)type:文件系統類型;4)opt-ions:掛接參數,以逗號隔開;5)dump和fsck order:用來決定控制dump、fsck程序的行爲。

f、創建etc/profile文件

#/etc/profile
echo "Processing /etc/profile"
echo "set user path"
PATH=/bin:/sbin:/usr/bin:/usr/sbin 
echo "set search library path"
LD_LIBRARY_PATH=/lib:/usr/lib
echo "set PS1" 
PS1='[\u@\h:\w]\$'
#PS1='[$USER@\h:\w]\$'
HOSTNAME='/bin/hostname'


export PATH LD_LIBRARY_PATH HOSTNAME PS1 

g、創建etc/mdev.conf文件

mdev.conf可以用來控制設備節點的所有者和權限,格式如下:
<device regex> <uid>:<gid> <octal permissions> 
mdev.conf還可以設置mdev在dev目錄下生成的設備節點的名字,如果該文件不存在,那麼在執行mdev –s這個命令時,會提示找不到mdev.conf。我們不需要mdev規則,所以只是touch生成一個空文件就OK了。當然也可以根據mdev的規則來 編寫mdev.conf。

g、創建用戶和組文件

拷貝主機etc目錄下的passwd、group、shadow文件到 rootfs/etc目錄下

(3)、構建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加入要自動運行的命令。參考之前的文件,已經修改。

從Linux-2.6.18開始,負責舊版本的設備管理系統devfs已被廢除,但新版本的udev是一個基於用戶空間的設備管理系統。在內核啓動時並不能自動創建設備節點,固需手動創建console和null兩個啓動過程必須的設備節點。將採用busybox中內置的mdev,一個簡化的udev版本。

clx@think:/work/armlinux/rootfs$ sudo mknod -m 600 dev/console c 5 1
clx@think:/work/armlinux/rootfs$ sudo mknod -m 600 dev/null c 1 3

mknod建立一個目錄項和一個特殊文件的  對應索引節點:語 法   mknod[必要參數][選擇參數][主設  備號][次設備號],建立的文件有三種 b:塊設備 c:字符設備   p:管道文件
如果不創建這兩個設備文件,在文件系統啓動時會出現錯誤信息,不能初始化控制檯。


3、製作根文件系統映像文件

clx@think:/work/armlinux$ sudo tar zxvf mkyaffs2image.tgz -C /
usr/sbin/mkyaffs2image
usr/sbin/mkyaffs2image-128M

clx@think:/work/armlinux$ sudo mkyaffs2image-128M rootfs rootfs.img

4、編譯測試

Please press Enter to activate this console. eth0: link up, 100Mbps, full-duplex, lpa 0xCDE1


Processing /etc/profile
set user path
set search library path
set PS1
root@MINI2440:/# ls
bin         etc         linuxrc     proc        sys         var
boot        home        lost+found  root        tmp
dev         lib         mnt         sbin        usr

root@MINI2440:/# ifconfig
eth0      Link encap:Ethernet  HWaddr 08:90:90:90:90:90  
          inet addr:192.168.1.250 Bcast:192.168.1.255  Mask:255.255.255.0
          UP BROADCAST RUNNING MULTICAST  MTU:1500  Metric:1
          RX packets:63 errors:0 dropped:0 overruns:0 frame:0
          TX packets:0 errors:0 dropped:0 overruns:0 carrier:0
          collisions:0 txqueuelen:1000 
          RX bytes:6919 (6.7 KiB)  TX bytes:0 (0.0 B)
          Interrupt:51 Base address:0xe300 


注:在後續的使用中存在的一些問題

1、不能卸載驅動模塊,運行modinfo顯示不出模塊信息

解決的方法,編譯內核模塊,並且要安裝到文件系統中去。是安裝在lib/modules/下面,此時這個目錄下還是空的。

make modules_install ARCH=arm INSTALL_MOD_PATH=/xxx/rootfs
INSTALL_MOD_PATH是指定安裝的路徑。

這種方法只是解決了運行modinfo的問題,內核模塊無法卸載的原因還沒有找到


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