Linux“三巨頭”已經完成了 2 個了,就剩最后一個 rootfs(根文件系統)了,本章就來學習一下根文件系統的組成以及如何構建根文件系統。這是 Linux 移植的最后一步,根文件系統構建好以后就意味著已經擁有了一個完整的、可以運行的最小系統。
? 根文件系統首先是內核啟動時所 mount(掛載)的第一個文件系統,內核代碼映像文件保存在根文件系統中,而系統引導啟動程序會在根文件系統掛載之后從中把一些基本的初始化腳本和服務等加載到內存中去運行。
? 根文件系統的這個“根”字就說明了這個文件系統的重要性,它是其他文件系統的根,沒有這個“根”,其他的文件系統或者軟件就別想工作。比如我們常用的 ls、mv、ifconfig 等命令其實就是一個個小軟件,只是這些軟件沒有圖形界面,而且需要輸入命令來運行,這些小軟件就保存在根文件系統中;
? 嵌入式 Linux 并沒有將內核代碼鏡像保存在根文件系統中,而是保存到了其他地方。比如 NAND Flash 的指定存儲地址、EMMC 專用分區中。根文件系統是 Linux 內核啟動以后掛載(mount)的第一個文件系統,然后從根文件系統中讀取初始化腳本,比如 rcS,inittab 等。根文件系統和 Linux 內核是分開的,單獨的 Linux 內核是沒法正常工作的,必須要搭配根文件系統。如果不提供根文件系統,Linux 內核在啟動的時候就會提示內核崩潰(Kernel panic)的提示。
? 根目錄,需要大體了解
?
? (來源于網絡)
? |?BusyBox 構建根文件系統
? BusyBox 是一個集成了大量的 Linux 命令(如?ls、mv、ifconfig 等命令)和工具的軟件,一般下載 BusyBox 的源碼,然后配置 BusyBox,選擇自己想要的功能,最后編譯即可。BusyBox 可以在其官網下載到,官網地址為:https://busybox.net/,官網比較簡陋:
?
?
? 讀者可以直接去官網下載,也可以使用原子提供的:
?
路徑為:1、例程源碼->6、BusyBox 源碼->busybox-1.29.0.tar.bz2? ? |?搭建NFS服務
? 一般在 Linux 驅動開發的時候都是通過 nfs 掛載根文件系統的,當產品最終上市開賣的時候才會將根文件系統燒寫到 EMMC 或者 NAND 中。
? 安裝并開啟 Ubuntu 中的 NFS 服務,使用如下命令安裝 NFS 服務:
?
sudo apt-get install nfs-kernel-server rpcbind? 等待安裝完成,安裝完成以后在用戶根目錄下創建一個名為“linux”的文件夾,以后所有的東西都放到這個“linux”文件夾里面,在“linux”文件夾里面新建一個名為“nfs”的文件夾;
?
?
創建的 nfs 文件夾供 nfs 服務器使用,以后我們可以在開發板上通過網絡文件系統來訪問 nfs 文件夾,要先配置 nfs,使用如下命令打開 nfs 配置文件/etc/exports: ?
sudo?gedit?/etc/exports? 打開/etc/exports 以后在后面添加如下所示內容:
? ?
/home/noah/linux/nfs *(rw,sync,no_root_squash)?
?
? 重啟 NFS 服務,使用命令如下: ?
sudo /etc/init.d/nfs-kernel-server restart?
?
? ? |?編譯 BusyBox 構建根文件系統
? 在nfs服務器目錄中創建一個名為rootfs的子目錄,然后把根文件系統放進去并解壓:
// 解壓命令 tar -vxjf busybox-1.29.0.tar.bz2?
?
?
? 修改 Makefile,添加編譯器
? ? 打開 busybox 的頂層 Makefile,添加 ARCH 和 CROSS_COMPILE的值,如下所示:
CROSS_COMPILE??=?/usr/local/arm/gcc-linaro-4.9.4-2017.01-x86_64_arm-linux-gnueabihf/bin/arm-linux-gnueabihf- ...... ARCH ?= arm?
?
?
? busybox 中文字符支持
? 如果默認直接編譯 busybox 的話,在使用串口工具的時候中文字符是顯示不正常的,中文字符會顯示為“?”,所以我們需要修改 busybox 源碼,取消 busybox 對中文顯示的限制; ? 打開文件busybox-1.29.0/libbb/printable_string.c,找到函數 printable_string,然后修改一下,主要就是禁止字符大于0X7F以后 break 和輸出‘?’:
?
? 接著打開文件 busybox-1.29.0/libbb/unicode.c,找到如下內容: ?
? 配置 busybox
? busybox有以下幾種配置選項:
? ①、defconfig,缺省配置,也就是默認配置選項。
? ②、allyesconfig,全選配置,也就是選中 busybox 的所有功能。
?
③、allnoconfig,最小配置。
? 一般使用默認配置即可,因此使用如下命令先使用默認配置來配置一下 busybox:
?
make defconfig? busybox 也支持圖形化配置,通過圖形化配置我們可以進一步選擇自己想要的功能,輸入如下命令打開圖形化配置界面:
?
make menuconfig?
?
? 設置Settings -> Build static binary (no shared libs)
? 選項“Build static binary (no shared libs)”用來決定是靜態編譯 busybox 還是動態編譯,靜態編譯的話就不需要庫文件,但是編譯出來的庫會很大。動態編譯的話要求根文件系統中有庫文件,但是編譯出來的 busybox 會小很多。這里我們不能采用靜態編譯!因為采用靜態編譯的話 DNS 會出問題!無法進行域名解析:
?
? 提示:選中Exit再按回車,就能返回上一級;
? 設置Settings -> vi-style line editing commands 按空格鍵進行選中和取消,這里要選中(出現*biao'sh);
?
? 配置Linux Module Utilities -> Simplified modutils 默認會選中“Simplified modutils”,這里我們要取消勾選!
? ?
? 配置Linux System Utilities -> mdev (16 kb) 確保下面的全部選中,默認都是選中的:
? 設置Settings -> Support Unicode 使能 busybox 的 unicode 編碼以支持中文:
? 最后按兩下ESC退出設置,并選擇YES保持存。 busybox 的配置就到此結束了,大家也可以根據自己的實際需求選擇配置其他的選項,不過對于初學者筆者不建議再做其他的修改,可能會出現編譯出錯的情況發生。
| 編譯 busybox ? ? ?
輸入如下指令進行編譯:
make ARCH=arm CROSS_COMPILE=arm-linux-gnueabihf- make ARCH=arm CROSS_COMPILE=arm-linux-gnueabihf- install CONFIG_PREFIX=/home/noah/linux/nfs/rootfs?
?
編譯完成以后會在 busybox 的所有工具和文件就會被安裝到 rootfs 目錄中,rootfs 目錄內容:
? rootfs目錄下新增bin、sbin和usr三個目錄,以及linuxrc文件。Linux內核linit進程最后會查找用戶空間的init程序,找到以后就會運行這個用戶空間的init程序,從而切換到用戶態。如果bootargs設置init=/linuxrc,那么linuxrc就是可以作為用戶空間的init程序,所以用戶態空間的 init 程序是 busybox 來生成的。
? busybox 的工作就完成了,但是此時的根文件系統還不能使用,還需要一些其他的文件,繼續來完善 rootfs。
? |?向根文件系統添加 lib 庫 ?
Linux 中的應用程序一般都是需要動態庫的,當然你也可以編譯成靜態的,但是靜態的可執行文件會很大。如果編譯為動態的話就需要動態庫,所以我們需要向根文件系統中添加動態庫。
? 向 rootfs 的“/lib”目錄添加庫文件 ?
在 rootfs 中創建一個名為“lib”的文件夾,lib 庫文件從交叉編譯器中獲取,前面搭建交叉編譯環境的時候將交叉編譯器存放到了“/usr/local/arm/”目錄中,具體路徑在:
/usr/local/arm/gcc-linaro-4.9.4-2017.01-x86_64_arm-linux-gnueabihf/arm-linuxgnueabihf/libc/lib? ?
?
? 此目錄下有很多的*so*(*是通配符)和.a 文件,這些就是庫文件,將此目錄下所有的*so*和.a文件都拷貝到 rootfs/lib 目錄中,拷貝命令如下:
?
cp *so* *.a /home/noah/linux/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,替換掉這個軟鏈接。 先將 rootfs/lib 中的 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/noah/linux/nfs/rootfs/lib/? 拷貝完成以后再到 rootfs/lib目錄下查看ld-linux-armhf.so.3文件詳細信息:
ls ld-linux-armhf.so.3 -l? ?
?
此時ld-linux-armhf.so.3已經不是軟連接了,而是實實在在的一個庫文件,而且文件大小為 724392B。 繼續進入如下目錄中: ?
/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/noah/linux/nfs/rootfs/lib/ -d? 復制完后,rootfs/lib 目錄的庫文件如圖:
?
? 向 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/noah/linux/nfs/rootfs/usr/lib/ -d? 完成以后的 rootfs/usr/lib 目錄如圖所示: ?
?
至此,根文件系統的庫文件就全部添加好了,可以使用“du”命令來查看一下 rootfs/lib 和rootfs/usr/lib 這兩個目錄的大小,命令如下:
cd rootfs //進入根文件系統目錄 du ./lib ./usr/lib/ -sh //查看 lib 和 usr/lib 這兩個目錄的大小結果如圖所示: ?
?
? 創建其他文件夾 ?
在根文件系統中創建其他文件夾,如 dev、proc、mnt、sys、tmp 和 root 等,命令如下:
mkdir?dev?proc?mnt?sys?tmp?root? ?
?
注意:根文件系統源碼和解壓后的源碼剪切到別的文件夾;
|?根文件系統初步測試
接下來使用測試一下前面創建好的根文件系統 rootfs,測試方法就是使用 NFS 掛載;
uboot里面的bootargs環境變量會設置root的值,需要將root的值改為NFS掛載,設置格式如下:
?
root=/dev/nfs nfsroot=[:] [, ] ip= : : : : : : : :
?
根據上面的格式bootargs環境變量的root值如下:
?
root=/dev/nfs?nfsroot=192.168.2.55:/home/noah/linux/nfs/rootfs,proto=tcp?rw?ip=192.168.2.50:192.168.2.55:192.168.2.1:255.255.255.0::eth0:off
?
啟動開發板,串口連接開發板,進入uboot命令行模式,然后設置bootargs環境變量,命令如下:
?
setenv?bootargs?'console=ttymxc0,115200?root=/dev/nfs?nfsroot=192.168.2.55:/home/noah/linux/nfs/rootfs,proto=tcp?rw?ip=192.168.2.50192.168.2.1off' saveenv
?
設置好以后使用“boot”命令啟動Linux內核;
?
tftp 80800000 zImage tftp 83000000 imx6ull-14x14-evk.dtb bootz 80800000 - 83000000
?
在進入根文件系統的時候會有下面這一行錯誤提示:
can't run '/etc/init.d/rcS': No such file or directory提示很簡單,說是無法運行“/etc/init.d/rcS”這個文件,因為這個文件不存在。制作的 rootfs 還是缺文件,后續一步一步的完善。 --END--
?
評論
查看更多