一、Busybox簡介
【特點】
(1-1)開源項目
Busybox是一個開源項目,遵循GPL v2協議。Busybox將眾多的UNIX命令集合進了一個很小的可執行程序中,可以用來替代GNU fileutils、shellutils等工具集。Busybox中各種命令與相應的GNU工具相比,所能提供的選項比較少,但是對於一般的應用場景也足夠了。Busybox主要用於嵌入式系統的開發中。
(1-2)程序本體較小
Busybox在編寫過程中對文件大小進行了優化,並考慮了系統資源有限(比如內存等)的情況。與一般的GNU工具集動輒幾M的體積相比,動態鏈接的Busybox只有幾百K,即使是采用靜態鏈接也只有1.M左右。Busybox按模塊設計,可以很容易地加入、去除某些命令,或增減命令的某些選項。
(1-3)使用簡單
在創建根文件系統的時候,如果使用Busybox來創建根文件系統,使用起來較為方便,只需要在/dev目錄下創建必要的設備節點,在/etc目錄下增加一些配置文件即可,當然如果Busybox是動態鏈接的,那么還需要在/lib目錄下包含相關的運行庫文件。
【官方資源】
URL:https://busybox.net/
Web頁面:
【注】本文所記錄內容時 使用的busybox版本為:1.29.0
二、Busybox源碼目錄結構
上圖是Busybox的目錄中的目錄和文件。
序號 | 目錄名稱 | 功能說明 |
---|---|---|
1 | applets | 實現applets框架的文件。目錄中包含了幾個main()的文件 |
2 | applets_sh | 此目錄包含了幾個作為shell腳本實現的applet示例。在“make install”時不會被自動安裝,需要使用時,手動處理 |
3 | arch | 包含用於不同體系架構的makefile文件。約束busybox在不同架構體系下的編譯構建過程 |
4 | archival | 與壓縮相關命令的實現源文件。 |
5 | configs | busybox自帶的默認配置文件 |
6 | console-tools | 與控制台相關的一些命令 |
7 | coreutils | 常用的一些核心命令。例如chgrp、rm等 |
8 | debianutils | 針對Debian的套件。 |
9 | e2fsprogs | 針對Linux Ext2 FS prog的命令。例如chattr、lsattr |
10 | editors | 常用的編輯命令。例如diff、vi等 |
11 | findutils | 用於查找的命令 |
12 | include | busybox項目的頭文件 |
13 | init | init進程的實現源碼目錄 |
14 | klibc-utils | klibc命令套件 |
15 | libbb | 與busybox實現相關的庫文件 |
16 | libpwdgrp | libpwdgrp相關的命令 |
17 | loginutils | 與用戶管理相關的命令 |
18 | mailutils | 與mail相關的命令套件 |
19 | miscutils | 該文件下是一些雜項命令,針對特定應用場景 |
20 | modutils | 與模塊相關的命令 |
21 | networking | 與網絡相關的命令,例如arp |
22 | printutils | Print相關的命令 |
23 | procps | 與內存、進程相關的命令 |
24 | runit | 與Runit實現相關的命令 |
25 | shell | 與shell相關的命令 |
26 | sysklogd | 系統日志記錄工具相關的命令 |
27 | util-linux | Linux下常用的命令,主要與文件系統操作相關的命令。 |
三、busybox的init進程
在linux內核啟動的最后階段,會調用run_init_process()函數啟動用戶空間進程,對於Busybox來說,它同樣將提供一個init程序,滿足linux內核最后階段的啟動跳轉。只要run_init_process()創建進程成功,那么此函數將不會返回了,從而從內核態進入了用戶態進程。
busybox的init程序的描述源文件位於源代碼下的init/init.c文件中。
核心功能的由init_main函數實現,此函數中內容較多,將在文章《busybox的init_main函數》中分析
int init_main(int argc UNUSED_PARAM, char **argv)
{
INIT_G();
if (argv[1] && strcmp(argv[1], "-q") == 0) {
return kill(1, SIGHUP);
}
#if DEBUG_SEGV_HANDLER
{
struct sigaction sa;
memset(&sa, 0, sizeof(sa));
sa.sa_sigaction = handle_sigsegv;
sa.sa_flags = SA_SIGINFO;
sigaction(SIGSEGV, &sa, NULL);
sigaction(SIGILL, &sa, NULL);
sigaction(SIGFPE, &sa, NULL);
sigaction(SIGBUS, &sa, NULL);
}
#endif
if (!DEBUG_INIT) {
sigprocmask_allsigs(SIG_BLOCK);
/* ........................... */
四、編譯busybox過程總結
在准備編譯前,可以先參考INSTALL、README以及examples目錄和docs目錄下的文件。獲取到相關的構建說明、安裝說明和一些使用的示例。
總體來說,編譯busybox與linux、以及u-boot的過程類似:
(1)使用
make menuconfig
先在宿主機上編譯出用於配置busybox的圖像化界面
這個過程中,可能會由於缺少一些庫(例如ncurses)而報錯,這時將其安裝即可解決。
對於嵌入式系統環境,是需要使用與嵌入式系統相關聯的【交叉編譯器】來進行編譯,所以,這里需要指定用於編譯busybox的交叉編譯器。
在busybox源碼目錄下的頂層makefile文件中添加:
CROSS_COMPILE ?= #交叉編譯器的路徑
ARCH ?= arm #對應的架構,這里以arm為例
(經測試,筆者的1.29版本busybox可以在圖形項中配置交叉編譯器的路徑,較低版本的可能需要手動指定)
(2)指定busybox編譯后的安裝路徑。
從上圖我們可以看出,Busybox默認的安裝路徑是源代碼目錄的_install目錄(該目錄不存在,安裝的時候自動創建)。
(3)可以更加實際情況設置busybox的動態/靜態編譯
筆者本文使用的【靜態編譯】
(4)使用make 編譯
(5)使用make install進行安裝,完成后如下圖:
使用靜態編譯構建出的busybox 軟件本體有1.4M大小左右
總結一下busybox的編譯構建過程:
1、使用make menuconfig構建出圖形配置界面。
2、通過配置圖形配置界面的選項配置busybox的安裝路徑、編譯工具、命令功能使能等。生成.config配置文件
3、使用make編譯busybox
4、使用make install命令安裝由busybox生成的根文件系統
5、完善根文件系統
6、使用和測試根文件系統