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