Linux 內核在系統引導期間所做的最后一件事是掛載根文件系統。Linux 內核沒有規定文件系統結構,但用戶空間應用程序希望在目錄結構中找到具有特定名稱的文件。因此,遵循 Linux 系統中出現的事實標準很有用。
構建根文件系統的“官方”規則包含在文件系統層次標準 (FHS) 中。FHS 定義了 Unix 操作系統中的目錄結構和內容(圖 1)。所有文件和目錄都出現在根目錄“/”下,即使它們存儲在不同的物理或虛擬設備上。但是,根據某些子系統(例如 X Windows),這些目錄中的一些可能存在于 Unix 系統上。為文件系統開發層次結構的過程早在 1993 年就開始于重組 Linux 系統的想法。當前的 FHS 標準(以前稱為 FSSTND)由非營利組織 Free Standards Group 管理,該組織由惠普、紅帽、IBM 和戴爾等主要軟件和硬件供應商組成。
這些目錄中的大多數都存在于所有 Unix 操作系統上,并且通常以幾乎相同的方式使用。
根文件系統的每個頂級目錄都有特定的用途。但是,其中許多僅與多用戶系統相關,其中管理員負責不同用戶使用的許多服務器或工作站。在嵌入式 Linux 系統中,通常沒有用戶和管理員,構建根文件系統的規則可以自由解釋。這并不意味著可以違反所有規則,但確實意味著違反其中一些規則對系統的正常運行幾乎沒有影響。有趣的是,商業發行版,甚至是傳統的工作站和服務器發行版,有時會偏離根文件系統的實際規則。
引導加載程序負責在內存中加載和初始化操作系統內核及其支持基礎設施。引導加載程序執行的典型任務包括選擇內核(Linux 桌面系統可能會提供一個內核列表以供您在引導期間按下一個鍵)并將初始文件系統加載到 RAM(initrd、initramfs 或類似的東西)。RAM 上的文件系統包含一個最小的環境來掛載根文件系統并啟動正常的引導過程。大多數臺式機和服務器系統都有擴展的系統固件(BIOS、UEFI、OpenFirmware 等),它提供了硬件設備配置和中斷路由詳細信息等信息。然而,嵌入式 Linux 通常沒有這些擴展。它通過引導加載程序完成工作,
因此,嵌入式 Linux 有一些獨特的引導加載程序要求。固件不僅必須將內核映像加載到系統內存中;它還必須對系統內存控制器進行編程、初始化處理器緩存、激活各種硬件設備、直接實現對網絡引導基礎設施的支持,以及執行許多其他活動。
根文件系統
Linux 內核與所謂的根文件系統協同工作。這是可以掛載根目錄的文件系統,包含使系統進入可以掛載其他文件系統的狀態所需的文件,并且可以啟動用戶空間守護程序和應用程序。大多數桌面和服務器發行版使用兩種類型的根文件系統:初始根文件系統和實際根文件系統。前者用于掛載和運行后者。根文件系統的目錄結構可以非常小,也可以包含通常的目錄集,包括 /dev、/bin、/etc 和 /sbin。內核啟動過程以初始化代碼 (init /main.c) 結束,其主要目的是創建和填充具有多個目錄和文件的初始根文件系統。然后嘗試在用戶模式下啟動 ID 為 1 的第一個進程,以執行在此初始文件系統上找到的文件。內核可以通過三種方式找到 init 進程將執行的文件。第一種方法是使用在引導時通過 init = kernel 參數指定的文件。如果未設置此參數,內核會嘗試一系列位置來查找名為“init”的文件。其中包括 /sbin /init、/etc /init 和 /bin /init。如果所有這些都失敗了,內核會嘗試執行它在 /bin /sh 中找到的任何 shell。如果后者沒有找到,內核會打印一個錯誤,說 init 找不到。第一種方法是使用在引導時通過 init = kernel 參數指定的文件。如果未設置此參數,內核會嘗試一系列位置來查找名為“init”的文件。其中包括 /sbin /init、/etc /init 和 /bin /init。如果所有這些都失敗了,內核會嘗試執行它在 /bin /sh 中找到的任何 shell。如果后者沒有找到,內核會打印一個錯誤,說 init 找不到。第一種方法是使用在引導時通過 init = kernel 參數指定的文件。如果未設置此參數,內核會嘗試一系列位置來查找名為“init”的文件。其中包括 /sbin /init、/etc /init 和 /bin /init。如果所有這些都失敗了,內核會嘗試執行它在 /bin /sh 中找到的任何 shell。如果后者沒有找到,內核會打印一個錯誤,說 init 找不到。
一旦 init 進程啟動,通常會運行其他用戶空間程序。在桌面或服務器系統上,這被稱為 sysvinit 進程,它包括一系列通常位于 /etc/rc.d 下的腳本。名稱“sysvinit”來自 Unix System V 中使用的機制,它定義了用于目錄和文件的命名方案。在嵌入式系統上,init 進程可以是一組定制設計的腳本,甚至是單個應用程序。一些桌面發行版將 sysvinit 替換為專為更快啟動而設計的替代品。
目錄:關鍵概念
首先,可以省略所有提供可擴展多用戶環境的目錄,例如 /home、/mnt、/opt 和 /root。您可以進一步刪除 /tmp 和 /var,但這些遺漏會影響某些程序的功能。
根據引導加載程序及其配置,可能不需要 /boot 目錄。這是因為引導加載程序可以在內核啟動之前從根文件系統檢索內核映像。
其余目錄 — /bin、/dev、/etc、/lib、/proc、/sbin、/sys 和 /usr — 對于系統的正常運行至關重要。
至少,您可能決定省略 /proc 和 /sys 并在沒有相應虛擬文件系統幫助的情況下配置內核。但是,ps、mount、ifconfig 和 sysfs 等基本命令需要訪問 proc 文件系統,這些命令也被越來越多的程序使用。所以如果想不用proc和sysfs,就需要準備好用自定義程序替換腳本,直接訪問內核調用接口。
/usr 和 /var 兩個主目錄具有默認層次結構,與根目錄的層次結構非常相似。
因此,系統所需的基本根文件系統目錄如下:$ Mkdir bin dev etc lib proc sbin sys tmp usr var boot
/tmp ( $ chmod 1777 tmp)的適當權限確保創建的文件只能由創建它們的用戶刪除。盡管大多數嵌入式 Linux 系統都是單用戶的,但在某些情況下嵌入式應用程序不需要以 root 權限運行,例如 OpenSSH 包。
對于嵌入式 Linux 系統,創建以下目錄 - $ mkdir usr /bin usr /lib usr /sbin - 足以正常系統操作。
當然,如果您需要額外的功能,例如 Web 服務器或打印驅動程序,則需要添加應用程序所需的額外目錄。
使用不同的根文件系統結構運行 Linux
如前所述,構建根文件系統的規則可以在 FHS 中找到。盡管大多數 Linux 應用程序和發行版都依賴于這些規則,但它們并不是由 Linux 內核強制執行的。事實上,內核源代碼很少對根文件系統的結構做出假設。可以構建具有不同根文件系統結構的嵌入式 Linux 系統。因此,有必要更改大多數軟件包的默認設置以使其符合新結構。
構建 FHS 根文件系統的規則得到所有在 Linux 系統上工作的開源和自由軟件開發人員的認可和共享。
初始根文件系統
初始根文件系統稱為初始 RAM 磁盤,駐留在內核在 RAM 中創建的磁盤映像中。在臺式機或服務器系統上,初始 RAM 磁盤用于加載驅動程序和初始化環境,以便可以安裝外部存儲系統(磁盤或網絡附加存儲)。
在嵌入式系統上,初始 RAM 磁盤可能是唯一安裝的文件系統,因為它包含用戶模式下所有必要的應用程序。或者,可以將初始 RAM 磁盤安裝到閃存驅動器或其他本地存儲介質。
在內核 2.4 中,初始 RAM 磁盤被稱為 initrd 映像。initrd 文件只能在引導時從外部源加載(MIPS 內核除外,它允許將映像集成到內核中)。在引導過程結束時,會卸載 initrd 映像以清理內存使用情況,然后再切換到更完整的根文件系統。
在 Kernel 2.6 中,創建和使用初始 RAM 磁盤的過程有所簡化。首先,這些文件被簡單地收集在一個名為 initramfs 而不是 initrd 的 CPIO 壓縮文件中。initramfs 文件始終內置在內核中(適用于所有硬件平臺);否則,內核構建過程會自動創建一個默認的 CPIO 存檔。
其次,initramfs 在啟動時不需要外部文件系統。Ramfs 支持內置于內核中,無法關閉。
Initramfs 是初始文件系統的 CPIO 存儲庫,在 Linux 引導過程中加載到內存中。它必須包含掛載實際根文件系統所需的所有設備驅動程序和工具。
為什么要使用 initramfs?
理想的配置是讓內核啟動處于足以使系統進入對用戶有用的狀態的最小狀態。這種最小狀態將允許內核盡可能小,并帶有一些編譯選項。
在任何系統上,尤其是在資源有限的系統上,您都希望內核本身保持較小,并且只動態加載引導最終系統所需的驅動程序模塊。大多數桌面系統使用 initramfs 來確定具有完整根文件系統的硬盤驅動器或其他存儲介質的類型。在這種情況下,initramfs 包含啟動腳本和主要驅動模塊。由于桌面硬件種類繁多,initramfs 可以足夠大且足夠復雜,可以選擇要安裝的硬件類型。
在小型系統上,情況可能會大不相同。可能沒有可用于保存另一個根文件系統的存儲空間。在這種情況下,initramfs 成為真正的根文件系統。
或者,小型系統可以使用具有只讀訪問權限的專用閃存驅動器,以避免意外破壞系統。在這種情況下,initramfs 將包含啟動腳本,這些啟動腳本會掛載閃存設備以模擬可寫分區,從而使系統能夠正常運行。
BusyBox 嵌入式系統
BusyBox(圖 2)是嵌入式系統的主力。它是單個二進制文件中常用的 Unix 實用程序的集合。命令行實用程序的選項通常少于其獨立對應項,但它們往往具有相似的功能。BusyBox 的主要目標是為資源有限的系統提供全套功能。
這是一個精心設計的包,非常易于使用。這個圖形配置實用程序在風格上與內核配置程序相似,它允許您通過指示要在二進制文件中包含哪些小程序來選擇必要的實用程序。選擇完全取決于您嘗試創建的系統。
BusyBox 的源代碼樹組織良好,實用程序根據其用途分類并存儲在單獨的子目錄中。例如,網絡實用程序和守護程序(如 httpd、ifconfig 等)位于 ./networking 目錄中;標準模塊(包括 insmod、rmmod 和 lsmod)的實用程序位于 ./modutils 目錄中;并且編輯器(例如 vi、awk 和 sed)位于 ./editors 目錄中。用于配置、構建和安裝的 makefile 和各種文檔位于樹的根目錄中。
Linux 引導加載程序
引導加載程序(圖 3)是一個由處理器執行的小型應用程序,其任務是將圖像加載到內存中并隨后引導系統。在 Linux 系統上,引導加載程序通常會加載內核。因為它們需要了解與底層硬件的交互,所以它們通常特定于正確選擇的操作系統上的計算機體系結構。
引導加載程序在嵌入式系統的開發中起著關鍵作用,因為它取決于它所基于的處理器的功能。例如,在大多數 Intel x86 或 x86_64 系統上,引導加載程序可以依賴基本輸入/輸出 (BIOS) 來執行設備初始化,因此可以專注于更高級別的功能,例如選擇要加載的特定內核。在大多數非 x86 硬件上,引導加載程序會自行初始化硬件;加載 ROM、閃存或存儲設備的內核或相關獨立應用程序映像;然后在開始在內存中執行之前切換到必要的內核選項。
在嵌入式 Linux 系統上,引導加載程序一步加載 Linux 內核。它可以是多級的,即由兩個或多個引導加載程序組成,其中第一個加載第二個。
x86 系統的引導加載程序
Linux 桌面和服務器平臺通常使用 x86 或 x86_64 處理器,因此多個引導加載程序可用于這些架構也就不足為奇了。Linux 系統最初使用 LOADLIN 引導加載程序和 LILO(Linux 加載程序)。今天,x86 和 x86_64 平臺的 Linux 發行版通常支持各種引導加載程序,具體取決于引導過程:
- Gran Unified Bootloader (GRUB) — Linux 桌面系統和服務器上最常用的引導加載程序;多級級聯引導加載程序,最常用于促進與引導過程的交互。最初的 GRUB 引導加載程序已被 GNU GRUB(也稱為 GRUB 2)取代。
- Syslinux — 一個多級引導加載程序系列,支持從 DOS/Windows 或 Linux 文件系統 (SYSLINUX)、網絡 (PXELINUX) 以及 DVD 和 CD-ROM 外圍設備 (isolinux) 引導。Syslinux 通常用于允許從網絡或從 USB、CD-ROM 和 DVD 設備啟動。
GRUB 傳統上被視為出色的引導加載程序,因為它提供了極其靈活的引導環境,在開發過程中非常有用,并且可以從 Syslinux 不支持的 Linux 文件系統類型引導。Syslinux 要小得多,但最好在不需要與引導過程交互的引導環境中使用。
英特爾提供了英特爾處理器引導加載程序開發套件 BLDK,它可以輕松開發用于基本嵌入式系統初始化的自定義引導加載程序。Timesys Desktop 不支持基于引導加載程序的 BLDK,以確保符合標準 Linux 引導過程并簡化使用 Desktop 跨多個硬件平臺進行開發的 Linux 平臺。
Das U-Boot,獨立于平臺的引導加載程序
許多引導加載程序(圖 4)特定于特定架構。引導加載程序支持各種架構和處理器的能力對于大型開發組織來說可能是一項重要功能。單個組織開發涵蓋多種架構的多個處理器的情況并不少見。在多個平臺上投資單個引導加載程序最終會降低開發成本。
Das U-Boot(圖 5)是高度可配置的多級,設計用于嵌入式 Linux。事實上,它是非 x86 系統上首選的引導加載程序。U-Boot 支持 Arm、Coldfire、MIPS、PPC、XScale 和類似的嵌入式系統的引導,也可以在 x86 系統上使用。靈活的 U-Boot 配置可輕松針對卡和處理器的特定需求進行定制,同時保持引導加載程序盡可能小。
U-Boot 的主要目標是提供有關 Linux 文件系統位置的信息,并從 NAND、SD/MMC 卡、UART 或以太網(通過 TFTP)恢復 Linux 內核;此外,它可以在 NAND (jffs2)、SRAM(RAM 磁盤)、SD/MMC(ext3 分區)或通過 IP 掛載 (NFS) 上指定根文件系統。
?
特定于平臺的引導加載程序
不同的嵌入式系統硬件為存儲和運行引導加載程序提供了不同數量的系統資源。Timesys Desktop Factory 包括對以下非 x86/x86_64 平臺引導加載程序的支持:
- APEX — 一些基于 Arm 的嵌入式系統中使用的引導加載程序。它最初是為夏普 LH 系列處理器編寫的,但后來被開發用于一系列 Arm 鏡頭,例如三星 S3C24xx 系列。
- at91bootstrap——Arm AT91 系統上常用的引導加載程序,通常作為 U-Boot 的第一階段引導加載程序,可以在加載 Linux 內核之前執行更復雜系統的初始化任務。它是 Atmel AT91 SoC 的二級引導加載程序,提供一組算法來處理硬件初始化,例如時鐘速度配置、PIO 設置和 DDR2 DRAM 初始化。
- at91bootstrap-3 — at91bootstrap 引導加載程序的擴展版本。
- blob — 與一些 StrongARM 處理器一起使用的開源引導加載程序。
- x-loader — 從 U-Boot 基本代碼派生的小型單階段引導加載程序,通常用于具有少量靜態內存的平臺,例如 OMAP 平臺,并且通常用作第一階段引導加載程序。
- yaboot — 適用于較舊的開放固件機器的 PowerPC 引導加載程序,在新的嵌入式 Linux 項目中很少遇到。通過編輯 /etc/ 文件夾中包含的 yaboot.conf 文件來配置 Yaboot,或者通過掛載包含程序的分區并修改相應的配置文件來配置 Yaboot。
紅靴
RedBoot(Debug Red Hat Embedded and Firmware Bootstrap 的縮寫)是一個開源應用程序,它使用實時硬件抽象層 eCos 操作系統為嵌入式系統提供引導固件。例如,RedBoot 用于空中客車 A380 和達美波音 767 的娛樂系統。
RedBoot 允許通過串行或以太網下載和執行嵌入式應用程序,包括與 GDB 協作提供調試支持的嵌入式 Linux 和 Ecos 應用程序。它還提供交互式命令行界面,允許管理閃存映像和配置可通過串行或以太網訪問的參數。
引導加載程序和嵌入式微控制器
引導加載程序是系統還原后運行的第一個代碼。其目的是使系統進入可以執行其主要功能的狀態。這需要通過選擇正確的映像來初始化硬件。由于其作用,引導加載程序通常放置在閃存的一部分中,以防止意外刪除或數據損壞。
引導加載程序是一個程序,它可以正確加載到微控制器中,允許您直接通過串行或 USB 端口對其進行編程,而不必使用編程器。這使您可以顯著加快固件開發過程和上市時間。
引導加載程序的操作可以根據來自用戶或來自外圍設備(例如,主機系統)的啟動信號進行同步。根據嵌入式系統,bootloader 信號可以首先驗證系統,確定當前設備應用程序是否有效,與主機通信以加載新應用程序,并重寫閃存應用程序。
大多數現代微控制器能夠在微秒內重新編程其閃存。引導加載程序的任務是驗證可引導加載映像并使用正確設置的中斷檢查代碼以中斷進程。通常,引導加載程序執行軟復位以允許應用程序恢復活動,并且應該能夠檢測、報告和處理引導加載操作期間發生的錯誤,例如電源故障、通信丟失和寫入錯誤(圖 6) .
審核編輯:湯梓紅
評論
查看更多