i.MX6ULL終結者Linux檔案系統的構建BusyBox構建根檔案系統

一隻流浪小法師發表於2020-11-14

製作根檔案系統有專門的工具可以使用,叫做BusyBox,BusyBox是標準Linux工具的一個單個可執行實現。BusyBox包含了一些簡單的工具,例如cat和echo,還包含了一些更大、更復雜的工具,例如grep、find、mount以及telnet。有些人將BusyBox稱為Linux工具裡的瑞士軍刀.簡單的說BusyBox就好像是個大工具箱,它整合壓縮了Linux的許多工具和命令。在本節我們使用BusyBox來製作一個根檔案系統。

1 獲取BusyBox原始碼

BusyBox可以從官網下載,官網地址為:https://busybox.net/,如圖 1.1所示:
在這裡插入圖片描述

圖 1.1

在官網左側的“Get BusyBox”欄有一行“Download Source”,點選“Download Source”即可開啟BusyBox的下載頁,如圖 1.2所示:
在這裡插入圖片描述

圖 1.2

在這裡插入圖片描述

圖 1.3

從上圖可以看出,目前最新的BusyBox 版本是 1.31.1。大家可以選擇其中的一個版本下載使用。不過還是建議大家使用我們提供的1.29.0 版本的 BusyBox。目前測試還沒有出現任何問題。BusyBox原始碼路徑:i.MX6UL終結者光碟資料/06_Linux驅動例程/第三方庫原始碼/busybox-1.29.0.tar.bz2。準備好原始碼之後就可以構建根檔案系統了。

32.3.2 編譯BusyBox構建根檔案系統

將準備好的BusyBox原始碼上傳到Ubuntu虛擬機器下並解壓。使用下列命令解壓:
tar -xvf busybox-1.29.0.tar.bz2
解壓完成後得到busybox-1.29.0目錄,如圖 2.1所示:
在這裡插入圖片描述

圖 2.1

下面幾個步驟開始配置busybox原始碼並編譯。
1、指定平臺和交叉編譯工具
開啟 busybox 的頂層 Makefile,修改CROSS_COMPILE(第164行)和ARCH(第190行)的值,如下所示:
164 CROSS_COMPILE ?= /usr/local/arm/gcc-linaro-4.9.4-2017.01-
x86_64_arm-linux-gnueabihf/bin/arm-linux-gnueabihf-

190 ARCH ?= arm
2、修改Busybox原始碼,支援中文
直接編譯busybox原始碼,使用串列埠電腦終端時中文顯示不正常。需要修改busybox原始碼,取消busybox 對中文顯示的限制。
修改檔案:busybox-1.29.0/libbb/printable_string.c,找到函式 printable_string,修改如下:

12 const char* FAST_FUNC printable_string(uni_stat_t *stats, const char *str) 
13 { 
14         char *dst; 
15         const char *s; 
16 
17         s = str; 
18         while (1) { 
...... 
30         if (c < ' ') 
31           break; 
32         /* 註釋掉下面這個兩行程式碼 */ 
33         /* if (c >= 0x7f) 
34             break; */ 
35         s++; 
36 } 
37 
38 #if ENABLE_UNICODE_SUPPORT 
39     dst = unicode_conv_to_printable(stats, str); 
40 #else 
41 { 
42         char *d = dst = xstrdup(str); 
43         while (1) { 
44             unsigned char c = *d; 
45             if (c == '\0') 
46                 break; 
47         /* 修改下面程式碼 */ 
48         /* if (c < ' ' || c >= 0x7f) */ 
49       if( c < ' ') 
50             *d = '?'; 
51         d++; 
52         } 
...... 
59 #endif 
60         return auto_string(dst); 
61 }

第 33 和 34 行,當字元大於 0X7F 以後就跳出去了。
第 48 ,如果支援 UNICODE 碼的話,當字元大於 0X7F 就直接輸出‘?’
因此針對這幾行進行修改。紅色部分的程式碼就是被修改以後的,主要就是禁止字元大於 0X7F 以後 break 和輸出‘?’。
檔案 busybox-1.29.0/libbb/unicode.c,修改內容如下所示:

1003 static char* FAST_FUNC unicode_conv_to_printable2(uni_stat_t 
*stats, const char *src, unsigned width, int flags)
1004 { 
1005       char *dst; 
1006       unsigned dst_len; 
1007       unsigned uni_count; 
1008       unsigned uni_width; 
1009 
1010       if (unicode_status != UNICODE_ON) { 
1011           char *d; 
1012           if (flags & UNI_FLAG_PAD) { 
1013               d = dst = xmalloc(width + 1); 
...... 
1022       /* 修改下面一行程式碼 */ 
1023       /* *d++ = (c >= ' ' && c < 0x7f) ? c : '?'; */ 
1024           *d++ = (c >= ' ') ? c : '?'; 
1025       src++; 
1026       } 
1027       *d = '\0'; 
1028       } else { 
1029           d = dst = xstrndup(src, width); 
1030           while (*d) { 
1031               unsigned char c = *d; 
1032               /* 修改下面一行程式碼 */ 
1033               /* if (c < ' ' || c >= 0x7f) */ 
1034                 if(c < ' ') 
1035                   *d = '?'; 
1036               d++; 
1037           } 
1038       } 
...... 
1044       return dst; 
1045   } 
...... 
1047 
1048   return dst; 
1049 } 

第1024和1034行程式碼是被修改以後的,同樣主要是禁止字元大於 0X7F 的時候設定為‘?’。busybox 中文字元支援跟程式碼修改有關的就改好了。
3、使用menuconfig進行配置
在進行配置之前先建立rootfs資料夾用於busybox原始碼編譯後安裝的目錄。可以自己選擇適合的目錄下進行建立(這裡我直接在當前busybox原始碼的目錄busybox-1.29.0下建立)。使用下列命令:
mkdir rootfs
如圖 2.2所示:
在這裡插入圖片描述

圖 2.2

建立資料夾後,我的絕對路徑是:/home/topeet/work/busybox/busybox-1.29.0。
然後開始進行busybox原始碼配置,在/home/topeet/work/busybox/busybox-1.29.0目錄下執行下列命令:
make menuconfig
命令執行後如圖 2.3所示:
在這裡插入圖片描述

圖 2.3

(1)指定安裝目錄
Settings —>
— Installation Options (“make install” behavior)
(/home/topeet/rootfs) Destination path for ‘make install’
填寫自己的rootfs資料夾的絕對路徑。填寫完成後如圖 2.4所示:
在這裡插入圖片描述

圖 2.4

(2)去掉簡要安裝
Linux Module Utilities —>
[ ] Simplified modutils
[] depmod (26 kb) (NEW)
[
] insmod (22 kb) (NEW)

預設會選中“Simplified modutils”,這裡我們要取消勾選。結果如圖 2.5所示:
在這裡插入圖片描述

圖 2.5

(3)靜態編譯busybox
Settings —>
[*] Build static binary (no shared libs)
預設沒有選中“Build static binary”,選上這個選項。如圖 2.6所示:
在這裡插入圖片描述

圖 2.6

(4)設定命令列風格和網路配置
Settings —>
[] Support /etc/networks
[
] vi-style line editing commands
這兩個選項預設沒有選中,修改後如圖 2.7所示:
在這裡插入圖片描述

圖 2.7

(5)mdev配置
Linux System Utilities —>
[] mdev (16 kb)
[
] Support /etc/mdev.conf
[] Support subdirs/symlinks
[
] Support regular expressions substitutions when renaming device
[] Support command execution at device addition/removal
[
] Support loading of firmware
確保這幾個都會選中,預設都是選中的。如圖 2.8所示:
在這裡插入圖片描述

圖 2.8

(6)busybox支援中文顯示
使能busybox 的 unicode 編碼
Settings —>
[] Support Unicode
[
] Check $LC_ALL, $LC_CTYPE and $LANG environment variables
修改後如圖 2.9所示:
在這裡插入圖片描述

圖 2.9

按需求配置好選項後,要儲存退出。
在這裡插入圖片描述

圖 2.10

因為修改過預設配置會有下列提示,是否儲存修改,選擇“yes”,儲存並退出。
在這裡插入圖片描述

圖 2.11

busybox 的配置就到此結束了,大家也可以根據自己的實際需求選擇配置其他的選項,不過對於初學者筆者不建議再做其他的修改,可能會出現編譯出錯的情況發生。
4、編譯busybox
配置好busybox後就可以編譯了,前面的menuconfig配置中已經指定了編譯結果的存放目錄。執行下面的命令進行編譯:
make -j4 //原始碼編譯
make install //編譯結果存放到指定目錄
執行結果如圖 2.12所示:
編譯完成:
在這裡插入圖片描述

圖 2.12

安裝完成結果:
在這裡插入圖片描述

圖 2.13

編譯完成以後會在 busybox 的所有工具和檔案就會被安裝到 rootfs 目錄中,rootfs目錄檔案內容如下圖所示:
在這裡插入圖片描述

圖 2.14

rootfs 目錄下有 bin、sbin 和 usr 這三個目錄,以及 linuxrc 這個檔案。Linux核心init程式最後會查詢使用者空間的init程式,找到以後就會執行這個使用者空間的init程式,從而切換到使用者態。如果bootargs設定 init=/linuxrc,那麼linuxrc就是可以作為使用者空間的init程式,所以使用者態空間的init程式是busybox來生成的。
busybox的工作就完成了,但是此時的根檔案系統還不能使用,還需要一些其他的檔案,我們繼續來完善 rootfs。

3 構建整個根檔案系統

在上一個小節中,編譯完成busybox原始碼後,生成了幾個根檔案系統下的資料夾,我們還需要手動建立其他剩餘的資料夾。如dev、etc、lib、mnt、proc、root、sys、tmp。建立完成後如圖 32.3.3.1所示:
在這裡插入圖片描述

圖 3.1

我們需要向lib和usr/lib資料夾下拷貝一些庫檔案。
1、向/lib資料夾下新增庫檔案
Linux 中的應用程式一般都是需要動態庫的,當然你也可以編譯成靜態的,但是靜態的可執行檔案會很大。如果編譯為動態的話就需要動態庫,所以我們需要向根檔案系統lib資料夾中新增動態庫。
lib庫檔案從交叉編譯器中獲取,前面搭建交叉編譯環境時,交叉編譯器的路徑為:/usr/local/arm/gcc-linaro-4.9.4-2017.01-x86_64_arm-linux-gnueabihf/。交叉編譯器中有很多庫檔案,製作簡單的根檔案系統,只需要把這些庫檔案放到根檔案系統中就可以了。
交叉編譯庫檔案路徑:
/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/topeet/work/busybox/busybox-1.29.0/rootfs/lib/ -d
後面的“-d”表示拷貝符號連結。有個庫檔案需要修改一下:ld-linux-armhf.so.3,這個庫檔案是個符號連結檔案,連線到了庫檔案ld-2.19-2014.08-1-git.so 上。如圖 3.2所示:
在這裡插入圖片描述

圖 3.2

庫檔案ld-linux-armhf.so.3在根檔案系統中不能作為符號連結檔案,需要修改為普通庫檔案。否則在根檔案系統中可執行程式不能執行。先將rootfs/lib中的ld-linux-armhf.so.3刪掉,重新拷貝一份到rootfs/lib目錄下。執行下列命令:
rm /home/topeet/rootfs/lib/ld-linux-armhf.so.3
cd /usr/local/arm/gcc-linaro-4.9.4-2017.01-x86_64_arm-linux-gnueabihf/arm-linux-gnueabihf/libc/lib
cp ld-linux-armhf.so.3 /home/topeet/work/busybox/busybox-1.29.0/rootfs/lib/
拷貝完成後再次檢視ld-linux-armhf.so.3 庫檔案資訊,如圖 3.3所示:
在這裡插入圖片描述

圖 3.3

此時ld-linux-armhf.so.3 庫檔案就不是符號連結檔案了。
繼續拷貝庫檔案,路徑如下:
/usr/local/arm/gcc-linaro-4.9.4-2017.01-x86_64_arm-linux-gnueabihf/arm-linux-gnueabihf/lib
拷貝此路徑下的so和.a檔案到rootfs/lib目錄下,命令如下:
cd /usr/local/arm/gcc-linaro-4.9.4-2017.01-x86_64_arm-linux-gnueabihf/arm-linux-gnueabihf/lib
cp so *.a /home/topeet/work/busybox/busybox-1.29.0/rootfs/lib/ -d
拷貝完成後,rootfs/lib目錄下檔案如圖 3.4所示:
在這裡插入圖片描述

圖 3.4

2、向/usr/lib目錄下新增庫檔案
在 rootfs 的usr目錄下建立一個名為lib的資料夾,將下面目錄下的庫檔案拷貝到/usr/lib目錄下。
/usr/local/arm/gcc-linaro-4.9.4-2017.01-x86_64_arm-linux-gnueabihf/arm-linux-gnueabihf/libc/usr/lib
進入上面的目錄,執行下列命令進行拷貝:
cp so *.a /home/topeet/work/busybox/busybox-1.29.0/rootfs/usr/lib -d
拷貝完成後,/usr/lib目錄如圖 3.5所示:
在這裡插入圖片描述

圖 3.5

至此,根檔案系統的庫檔案全部新增完畢。整個根檔案系統就已經準備好了。在這裡插入圖片描述

相關文章