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