前面幾篇介紹了uboot的移植與內核的移植,本篇進行根文件系統的構建,這是Linux移植三大組成部分的最后一步,根文件系統構建好后,就構成了一個基礎的、可以運行的嵌入式Linux最小系統。
1 根文件系統簡介
Linux的根文件系統一般也叫做 rootfs,Linux的根文件系統更像是一個文件夾或者叫做目錄,在這個目錄里面會有很多的子目錄。根目錄下和子目錄中會有很多的文件,這些文件是Linux運行所必須的,比如庫、常用的軟件和命令、設備文件、配置文件等等。
根文件系統的這個“根”字就說明了這個文件系統的重要性,它是其他文件系統的根,沒有這個“根” ,其他的文件系統或者軟件就別想工作。比如我們常用的 ls、mv、ifconfig 等命令其實就是一個個小軟件,只是這些軟件沒有圖形界面,而且需要輸入命令來運行。這些小軟件就保存在根文件系統中。
在構建根文件系統之前,先來看一下根文件系統里面都有些什么內容,根文件系統的目錄名字為‘/’ ,就是一個斜杠:
根文件系統的各個文件夾的作用如下:
目錄 | 描述 |
---|---|
/bin | 此目錄下存放著系統需要的可執行文件,一般都是一些命令,比如 ls、mv 等命令 |
/dev | dev 是 device 的縮寫,所以此目錄下的文件都是和設備有關的。在Linux下一切皆文件,即使是硬件設備,也是以文件的形式存在的,比如/dev/ttymxc0就表示串口0 |
/etc | 此目錄下存放著各種配置文件 |
/lib | lib是library的簡稱,也就是庫的意思,因此此目錄下存放著Linux所必須的庫文件 |
/mnt | 臨時掛載目錄,一般是空目錄,可以在此目錄下創建空的子目錄,比如/mnt/sd、/mnt/usb,這樣就可以將SD卡或者U盤掛載到/mnt/sd 或者/mnt/usb 目錄中 |
/proc | 此目錄一般是空的,當Linux系統啟動以后會將此目錄作為proc文件系統的掛載點,proc是個虛擬文件系統,沒有實際的存儲設備。proc里面的文件都是臨時存在的,一般用來存儲系統運行信息文件 |
/usr | 注意,usr不是user的縮寫,而是Unix Software Resource的縮寫,即Unix操作系統軟件資源目錄。Linux 一般被稱為類Unix操作系統。既然是軟件資源目錄,因此/usr 目錄下也存放著很多軟件,一般系統安裝完成以后此目錄占用的空間最多 |
/var | 此目錄存放一些可以改變的數據 |
/sbin | 此目錄頁用戶存放一些可執行文件, 但是此目錄下的文件或者說命令只有管理員才能使用,主要用于系統管理 |
/sys | 系統啟動以后此目錄作為 sysfs 文件系統的掛載點,sysfs是一個類似于 proc文件系統的特殊文件系統,sysfs也是基于RAM的文件系統,也就是說它也沒有實際的存儲設備。此目錄是系統設備管理的重要目錄 |
/opt | 可選的文件、軟件存放區,由用戶選擇將哪些文件或軟件放到此目錄中 |
2 BusyBox構建根文件系統
2.1 BusyBox簡介
BusyBox是一個集成了大量的Linux命令(如ls、mv、ifconfig 等命令)和工具的軟件。借助BusyBox,進行配置和編譯,就可以方便的構建一個嵌入Linux平臺所需要的根文件系統。
課程BusyBox官網https://busybox.net/下載源碼,如下圖。
左側的“Get BusyBox”欄有一行“Download Source” ,點擊“Download Source”即可打開 BusyBox 的下載頁。
目前最新的 BusyBox 版本是1.33.1,但這里使用正點原子提供的1.29.0版本的BusyBox(busybox-1.29.0.tar.bz2)
2.2 搭建NFS服務
一般在Linux驅動開發的時候都是通過NFS掛載根文件系統的,當調試好之后再將根文件系統燒寫到 EMMC或者NAND中,因此需要先在ubuntu虛擬機中構建NFS服務:
sudo apt-get install nfs-kernel-server rpcbind
等待安裝完成,在合適的地方新建一個名為“nfs”的文件夾,供NFS服務器使用。
如我的創建目錄為:/home/xxpcb/myTest/nfs
在使用NFS之前,還需要先配置NFS,修改配置文件/etc/exports
,在后面添加如下所示內容:
/home/xxpcb/myTest/nfs *(rw,sync,no_root_squash)
最后重啟NFS服務即可:
sudo /etc/init.d/nfs-kernel-server restart
正常情況會出現如下圖,表示設置成功:
注:我第一次設置時,文件路徑中的一個大小寫字母搞錯了,導致重啟NFS時提示失敗(如下圖),所以在設置時要注意細節!
2.3 修改配置BusyBox
在nfs服務器目錄中創建一個名為rootfs
的子目錄,用來存放我們的根文件系統。
將busybox-1.29.0.tar.bz2
發送到Ubuntu中的合適位置(我存放在 /home/xxpcb/myTest/imx6ull/dts)并解壓:
tar -vxjf busybox-1.29.0.tar.bz2
解壓后的文件如下:
2.3.1 修改Makefile添加編譯器
注:這一步可以不修改,這里修改Makefile的目的是為了在編譯時,可以不用在指定編譯器的架構,從而可以縮短手動輸入指令的長度。但我此次測試時,修改Makefile后,輸入make指令的命令進行編譯時,不指定編譯器,還是會提示編譯器找不到之類的問題。所以,此次的測試,我就沒有修改這個Makefile。
如果堅持要修改Makefile,就是修改如下的地方,指定編譯器與架構(本篇進行實驗時沒有修改)。
2.3.2 busybox中文字符支持
現在如果直接編譯busybox的,在使用串口工具的時候是不支持中文顯示的,中文字符會顯示為“?” 。可以通過busybox源碼,來取消 busybox對中文顯示的限制。
打開文件busybox-1.29.0/libbb/printable_string.c,找到函數printable_string,吧某些程序注釋掉,修改后的函數內容如下:
主要就是禁止字符大于0X7F以后 break 和輸出‘?’
接著打開文件busybox-1.29.0/libbb/unicode.c,修改如下內容:
2.3.3 配置busybox
有以下幾種配置選項:
defconfig:缺省配置,也就是默認配置選項
allyesconfi:全選配置,也就是選中 busybox 的所有功能
allnoconfig:最小配置
一般使用默認配置即可,因此使用如下命令先使用默認配置來配置一下 busybox:
make ARCH=arm CROSS_COMPILE=arm-linux-gnueabihf- defconfig
busybox也支持圖形化配置,通過圖形化配置我們可以進一步選擇自己想要的功能,輸入如下命令打開圖形化配置界面:
make ARCH=arm CROSS_COMPILE=arm-linux-gnueabihf- menuconfig
(1) 設置Settings -> Build static binary (no shared libs)
選項“Build static binary (no shared libs)”用來決定是靜態編譯還是動態編譯,靜態編譯的話就不需要庫文件,但是編譯出來的庫會很大。動態編譯的話要求根文件系統中有庫文件,但是編譯出來的 busybox 會小很多。這里我們不使用靜態編譯,所以保持默認不選即可。
(2) 設置Settings -> vi-style line editing commands
這個要勾選,通過按鍵“y”實現勾選,使得方括號內出現星號
(3) 配置Linux Module Utilities -> Simplified modutils
默認會選中“Simplified modutils” ,這里我們要取消勾選! 使用鍵盤上的“n”鍵取消方括號中的星號。
(4) 配置Linux System Utilities -> mdev (16 kb)
確保下面的全部選中,默認都是選中的
(5) 設置Settings -> Support Unicode
要將默認沒有勾選的Check $LC_ALL
項選中!
最后按兩下ESC退出設置,并選擇YES保持存。
2.4 編譯busybox構建根文件系統
輸入如下指令進行編譯:
make ARCH=arm CROSS_COMPILE=arm-linux-gnueabihf-
make ARCH=arm CROSS_COMPILE=arm-linux-gnueabihf- install CONFIG_PREFIX=/home/xxpcb/myTest/nfs/rootfs
編譯完成以后, busybox的所有工具和文件就會被安裝到rootfs目錄中,如下圖:
rootfs目錄下有bin、sbin和usr三個目錄,以及linuxrc文件。Linux內核linit進程最后會查找用戶空間的init程序,找到以后就會運行這個用戶空間的init程序,從而切換到用戶態。如果bootargs設置init=/linuxrc,那么linuxrc就是可以作為用戶空間的init程序。
2.5 向根文件系統添加lib庫
busybox編譯完成后,此時的根文件系統還不能使用, 還需要一些其他的文件。
2.5.1 向rootfs/lib中添加
上面的busybox使用的是動態庫編譯,所以還需要向根文件系統中添加動態庫。
先在rootfs中創建一個名為“lib”的文件夾。lib庫文件從交叉編譯器中獲取,之前搭建交叉編譯環境的時候將交叉編譯器存放到了“/usr/local/arm/”目錄中,進入對應的目錄:
cd /usr/local/arm/gcc-linaro-4.9.4-2017.01-x86_64_arm-linux-gnueabihf/arm-linux-gnueabihf/libc/lib
此目錄下有很多的so和.a 文件,這些就是庫文件,將此目錄下所有的so和.a文件都拷貝到 rootfs/lib 目錄中:
cp *so* *.a /home/xxpcb/myTest/nfs/rootfs/lib/ -d
后面的“-d”表示拷貝符號鏈接,這里有個比較特殊的庫文件:ld-linux-armhf.so.3,此庫文件也是個符號鏈接,相當于 Windows 下的快捷方式。會鏈接到庫 ld-2.19-2014.08-1-git.so 上,輸入命令如下指令查看此文件詳細信息:
ls ld-linux-armhf.so.3 -l
ld-linux-armhf.so.3 后面有個“->” ,表示其是個軟連接文件,鏈接到文件ld-2.19-2014.08-1-git.so,因為其是一個“快捷方式” ,因此大小只有 24B。但是,ld-linux-armhf.so.3不能作為符號鏈接,否則的話在根文件系統中執行程序無法執行!所以我們需要重新復制ld-linux- armhf.so.3,替換掉這個軟鏈接。
先刪除這個軟連接文件:
rm ld-linux-armhf.so.3
然后重新進入到 /usr/local/arm/gcc-linaro-4.9.4-2017.01-x86_64_arm-linux-gnueabihf/arm- linux-gnueabihf/libc/lib 目錄中,重新拷貝ld-linux-armhf.so.3,命令如下:
cp ld-linux-armhf.so.3 /home/xxpcb/myTest/nfs/rootfs/lib/
拷貝完成以后再到 rootfs/lib 目錄下查看ld-linux-armhf.so.3文件詳細信息,此時ld-linux-armhf.so.3 已經不是軟連接了,而是實實在在的一個庫文件,而且文件大小為 724392B。
繼續進入如下目錄中:
cd /usr/local/arm/gcc-linaro-4.9.4-2017.01-x86_64_arm-linux-gnueabihf/arm-linux-gnueabihf/lib
此目錄下也有很多的的so和.a 庫文件,我們將其也拷貝到 rootfs/lib 目錄中,命令如下:
cp *so* *.a /home/xxpcb/myTest/nfs/rootfs/lib/ -d
rootfs/lib 目錄的庫文件就這些了,完成以后的rootfs/lib目錄如圖:
2.5.2 向rootfs/usr/lib中添加
在rootfs/usr
目錄下創建一個名為lib的目錄, 將如下目錄中的庫文件拷貝到rootfs/usr/lib目錄下:
/usr/local/arm/gcc-linaro-4.9.4-2017.01-x86_64_arm-linux-gnueabihf/arm-linux-gnueabihf/libc/usr/lib
將此目錄下的so和.a 庫文件都拷貝到rootfs/usr/lib目錄中:
cp *so* *.a /home/xxpcb/myTest/nfs/rootfs/usr/lib/ -d
完成以后的rootfs/usr/lib目錄為:
至此,根文件系統的庫文件就全部添加好了,可以在rootfs
目錄下使用“du”命令來查看一下/lib和/usr/lib 這兩個目錄的大小:
du ./lib ./usr/lib/ -sh
2.6 創建其他文件夾
在根文件系統中創建其他文件夾,如 dev、proc、mnt、sys、tmp 和 root 等,創建完后的效果:
3 根文件系統初步測試
3.1 bootargs環境變量設置
使用NFS掛載的方式來測試上面創建好的根文件系統rootfs。
uboot里面的bootargs環境變量會設置root的值,需要將root的值改為NFS掛載,設置格式如為:
root=/dev/nfs nfsroot=[:][,] ip=::::::::
:服務器IP,存放根文件系統的Ubuntu的IP地址,比如我的192.168.5.105。
:根文件系統的存放路徑,比如我的就是/home/xxpcb/myTest/nfs/rootfs。
:NFS 的其他可選選項,一般不設置。
:客戶端IP ,開發板的IP地址,Linux內核啟動以后就會使用此IP地址來配置開發板。我的為92.168.5.102。
:網關地址,我的就是 192.168.5.1。
:子網掩碼,我的就是 255.255.255.0。
:客戶機的名字,一般不設置,此值可以空著。
:設備名,也就是網卡名,一般是 eth0,eth1….,正點原子與野火的開發板均為ENET2為eth0,ENET1為eth1。這里我們使用ENET2,所以網卡名就是 eth0。
:自動配置,一般不使用,所以設置為 off。
:DNS0 服務器 IP 地址,不使用。
:DNS1 服務器 IP 地址,不使用。
根據上面的格式bootargs環境變量的root值如下:
root=/dev/nfs nfsroot=192.168.5.105:/home/xxpcb/myTest/nfs/rootfs,proto=tcp rw ip=192.168.5.102:192.168.5.105:192.168.5.1:255.255.255.0::eth1:off
啟動開發板,串口連接開發板,進入uboot命令行模式,然后設置bootargs環境變量,命令如下:
setenv bootargs 'console=ttymxc0,115200 root=/dev/nfs nfsroot=192.168.5.105:/home/xxpcb/myTest/nfs/rootfs,proto=tcp rw ip=192.168.5.102:192.168.5.105:192.168.5.1:255.255.255.0::eth1:off'
saveenv
設置好以后使用“boot”命令啟動Linux內核
Linux內核的啟動還是按照上一篇介紹的,使用tftp將zImage和設備樹傳輸到開發板中運行。
這里注意一下,因為此次測試,我將zImage和dtb文件移入了tftp目錄中的nxp文件夾中,所以傳輸指令需要修改一下:
setenv bootcmd 'tftp 80800000 nxp/zImage; tftp 83000000 nxp/imx6ull-myboard.dtb; bootz 80800000 - 83000000'
saveenv
然后就可以使用boot命令來進行tftp傳輸了。
3.2 NFS掛載錯誤與解決方法
3.2.1 錯誤提示
在使用boot命令來進行tftp傳輸了,啟動內核時,出現了NFS根文件系統不能掛載的錯誤:
VFS: Unable to mount root fs via NFS, trying floppy.
VFS: Cannot open root device "nfs" or unknown-block(2,0): error -6
3.2.2 無效的解決方法
先是嘗試了多種方法,都不能解決問題,這些無效的方法包括:
嘗試修改配置,將Linux System Utilities ->Support mounting NFS file選中(無效)
嘗試將nfs目錄的下的rootfs文件夾賦予777的權限(無效)
嘗試換用其它的串口軟件(SecureCRT)來操作(無效)
3.2.3 有效的解決方法
最后,參考這篇博文:https://blog.csdn.net/InFoport/article/details/90317697
通過在bootargs添加中添加nfsvers=4
,這個選項,就可以正常掛載nfs的文件系統了:
setenv bootargs 'console=ttymxc0,115200 root=/dev/nfs nfsroot=192.168.5.105:/home/xxpcb/myTest/nfs/rootfs,proto=tcp,nfsvers=4 rw ip=192.168.5.102:192.168.5.105:192.168.5.1:255.255.255.0::eth1:off'
注:無效方法中的Linux System Utilities ->Support mounting NFS file,因開啟后也不起作用,后續測試就將其改為默認的不勾選。
3.3 文件系統使用測試
按下回車鍵,就進入了文件系統,使用ls命令就可以看到了系統文件。
再使用touch命令來新建一個中文名稱的文件,也是OK的。
4 總結
本篇使用BusyBox來構建根文件系統,并通過NFS網絡調試的方式實現根文件系統掛載測試,實測時解決了NFS根文件系統不能掛載的問題,最終根文件系統基本功能測試正常。
審核編輯:湯梓紅
-
嵌入式
+關注
關注
5082文章
19126瀏覽量
305194 -
Linux
+關注
關注
87文章
11304瀏覽量
209498 -
移植
+關注
關注
1文章
379瀏覽量
28132
發布評論請先 登錄
相關推薦
評論