- [Compilation Process、 make、Makefile](https://hackmd.io/@YungHuiHsu/rJyCf2vYp) - [[Linux_BSP] Week1。Linux架構、 Boot、kernel、driver、device tree 筆記](https://hackmd.io/@YungHuiHsu/ryZ1i45dT) - [[Linux_BSP] Week2。UART與GPIO控制](https://hackmd.io/@YungHuiHsu/B1e_heHt6) - [[Linux_BSP] Week3_1。I2C 通訊、GMSL2 Camera](https://hackmd.io/@YungHuiHsu/HkaQBH0K6) - [[Linux_BSP] Week3_2。GMSL2 Camera](https://hackmd.io/@YungHuiHsu/Hyjmb5V96) - [[Linux_BSP] Week4。HPC Debug](https://hackmd.io/@YungHuiHsu/HknGTEw9p) --- # Linux 開機流程 :::success - 學習目標: 1. 了解 Linux 各部架構 2. 了解 Linux 開機流程 ::: ## Architecture (架構) > Linux即為核心與系統呼叫介面那兩層 ![image](https://hackmd.io/_uploads/rk8hunidT.png =200x) [source: linux.vbird.org/linux_basic/centos7](https://linux.vbird.org/linux_basic/centos7/0110whatislinux.php) | ![image](https://hackmd.io/_uploads/Byqmoh2_T.png =350x) | ![image](https://hackmd.io/_uploads/H1gCacnsu6.png =350x) | | -------- | --------------------------------------------------- | | [Introduction To Linux Operating System](https://www.c-sharpcorner.com/article/introduction-to-linux-operating-system/) | [Fundamental Architecture of Linux](https://www.engineersgarage.com/kernel-architecture-of-linux-part-7-15/) - 左圖 反映了 Linux 操作系統的層次架構,涵蓋了 User Space 和 Kernel Space 的不同元件: - **User Space (用戶空間)**:這是普通用戶應用程序運行的空間,具有較低的執行權限來保護系統免受不當操作的影響。在此空間中,包含系統軟體(System Softwares)、使用者進程(User Process)、用戶工具(User Utility)和編譯器(Compilers)等運行,提供了用戶與系統互動的界面和工具,如文字編輯器、瀏覽器或開發工具等。 - **Kernel Space (核心空間)**:這裡是操作系統核心運行的空間,擁有高等級的控制權限,用於直接管理硬體資源和系統調用。核心空間包括核心(Kernel)本身和核心模組(Kernel Modules),負責處理進程調度、記憶體管理、Driver程序操作、網路堆疊等關鍵功能。 這兩個空間之間通過系統呼叫介面(如圖中所未顯示)進行通信,這樣,用戶空間的應用程序可以請求核心提供服務而不需要直接操作硬體。這種分離保證了操作系統的安全性和穩定性。 - 右圖 - 硬體平台 (Hardware Platform) Linux系統的物理基礎,包括但不限於以下幾個關鍵部分: * CPU: 負責處理指令和控制其他硬體元件。 * 記憶體: 存儲程序和數據,供CPU快速訪問。 * I/O 裝置: 包括硬碟、網路介面卡等,負責數據的輸入輸出操作。 * 外部連接介面: 如USB、串列埠等,用於連接外部裝置。 - 用戶空間 (User Space) :penguin: 用戶空間是應用程序運行的地方。Linux系統中執行所有用戶程序和應用程序的區域。與核心空間相比,用戶空間具有一定的限制和保護機制。 :::success 提供了應用程序與核心之間溝通的接口。它包含了系統調用的封裝和其他基本功能,讓用戶空間的應用程序可以執行操作,如文件處理、設備控制和其他核心級別的任務。 ::: - 程序執行與硬體訪問 - **隔離與保護**: 用戶空間中的程序不能直接訪問記憶體和硬體資源。這種隔離提供了保護,防止用戶程序對系統的整體穩定性造成影響。 - **通過核心空間訪問硬體**: 當用戶空間的程序需要與硬體互動時,它們必須通過核心空間來實現。這意味著所有硬體訪問請求都需要經過核心的管理和控制。 - 記憶體訪問 - **系統呼叫限制**: 用戶空間的程序或程序只能通過系統呼叫來訪問一部分記憶體。這種設計確保了記憶體訪問的安全性和有效性。 - **保護機制**: 由於有完整的保護機制,用戶模式下的崩潰通常是可恢復的,不會影響到系統的其他部分。 - GNU C Library (glibc) - **用戶空間與核心空間的橋樑**: `glibc` 提供了一種機制,使得用戶空間的應用程序能夠切換到核心空間。這是通過封裝系統呼叫來實現的,當應用程序需要執行核心級別的操作時(如檔案存取、網路通訊等),它們會使用 `glibc` 提供的函式。 - **應用程序開發**: 對於應用程序開發者來說,`glibc` 提供了一個豐富的函式庫,使得他們可以更容易地編寫能夠在Linux系統上運行的程序,而無需深入了解底層的核心細節。 - 核心空間 (Kernel Space) :pencil2: 負責管理硬體資源和系統調用 :::success Linux系統的核心部分,它直接訪問全部記憶體並與硬體如RAM、硬碟等直接互動。核心空間被劃分為不同的模塊和區塊,管理著所有在核心空間和用戶空間運行的應用程序的操作。 ::: - **硬體獨立性**: Kernel與硬體無關,對於Linux支持的所有硬體處理器(如Intel、ARM、Atmel等)都是通用的。 - **資源管理**: Kernel在Kernel Space內充當資源管理員,執行程序管理、檔案管理、記憶體管理、中斷處理、程序調度等任務。 - **強大的結構**: Kernel是一個強大的結構,能夠處理各種操作,從基本的檔案讀寫到複雜的網路通訊和硬體控制。 ## Linux system 組成 ![image](https://hackmd.io/_uploads/HJADjh2dp.png =400x) [Linux Kernel and process scheduling](https://www.digihunch.com/2018/11/linux-kernel-and-process-scheduling/) Linux系統由三個主要的程式碼主體組成,與最傳統的UNIX實現方式一致: - 核心(Kernel): - Linux Kernel 是 Linux 作業系統的核心部分,負責管理系統的所有硬體和軟件交互。它是一個大型的、複雜的程式,負責處理 CPU、記憶體管理、檔案系統、裝置控制、網路功能等。 - Linux Kernel是一個單一的、整體的二進制檔案monolithic binary(為了最佳性能),在處理器的特權模式(又稱核心模式)下運行,實現了作為操作系統所需的所有功能。核心可以在運行時動態地加載(和卸載)模組。 - Kernel中不包含用戶代碼。任何不需要在核心模式下運行的操作系統支持代碼都放在系統庫(system libraries)中,並在用戶模式下運行。用戶模式只能訪問系統資源的受控子集(controlled subset of system resources)。 - Kernel 是用 C 語言和少量的匯編語言編寫的程式碼。 - 這些程式碼被編譯成一個二進制映像(例如 vmlinux 或壓縮後的 bzImage),在系統啟動時由 Bootloader 加載到記憶體並執行。 - 核心模組(Kernel Module) - Kernel Module 是 Linux 系統中的一種特殊程式,它們可以在系統運行時**動態地加載或卸載到 Kernel** 中。**這些模組通常用於添加硬體驅動程式**、檔案系統支援或其他擴展功能,而無需重新啟動系統或重新編譯 Kernel :::info 驅動程式(Driver)通常是 Kernel Module 的一種特殊類型,主要負責硬體裝置的功能控制。它們是系統與硬體之間的接口,負責翻譯 Kernel 的通用指令為特定硬體裝置的控制信號,並將硬體的狀態信息回傳給 Kernel。驅動程式是 Kernel Module 的重要組成部分,但並非所有 Kernel Module 都是驅動程式。Kernel Module 還可能包括其他類型的擴展,例如檔案系統、網路協議支援等 ::: :::info Kernel Module 可以被視為 Kernel 的子集。它們允許系統在運行時動態地擴展功能。這包括但不限於動態加載和卸載硬體驅動程式、檔案系統支援等。Kernel Module 提供了一種機制,讓系統能夠在不重啟或重新編譯 Kernel 的情況下添加或移除這些功能 ::: - 系統庫(System Library): - System Library通過定義一組標準函數,使應用程序能夠與核心進行交互。這些函數實現了大部分無需完整特權的核心代碼的作業系統功能。最重要的系統庫是libc(C庫),它提供了標準C庫並實現了Linux系統調用接口的用戶模式部分,以及其他關鍵的系統級接口。 - System libraries允許應用程序向Linux核心發起系統呼叫( system call)。進行系統呼叫涉及從非特權的用戶( unprivileged user)模式轉移到特權的核心模式(privileged kernel mode)。這些庫還提供了一些不對應於系統呼叫的常用功能,如排序算法、數學函數和字串操作常用功能。 - 系統工具(System utilities) - System utilities所有初始化並管理系統所需的程序,如設置網路接口和從系統中添加或移除用戶的工具。用戶工具包括殼(shell)、檔案複製工具等。 ### Linux Kernel :penguin: Linux Kernel是操作系統的核心部分,**負責管理硬體資源和協調軟體運行** ![image](https://hackmd.io/_uploads/ByOfi2jdp.png =600x) > Full Architecture of Kernel > [source: Kernel Architecture Of Linux](https://www.engineersgarage.com/kernel-architecture-of-linux-part-7-15/) > > Linux kernel採用模組化架構, kernel內每個區塊(例如檔案管理)都是用 C 語言編寫的代碼片段。圖中顯示了核心的各個子系統及其與硬體的關聯: > > - 程序管理 (Process management): > - 程序管理是處理同時運行的各種程序的管理。程序是“正在運行程序”的實例,如打開文件、訪問Driver器、訪問外部資源(例如打印機)等,並且可以創建和銷毀。 > - 程序管理提供有關程序正在發生的情況的信息,並管理其優先級,例如應為程序分配哪個地址,為程序分配文件,程序的狀態(如運行,等待,停止) > - 記憶體管理 (Memory management): > - 記憶體管理是Kernel的最重要部分,負責將地址空間分配給程序(process)和應用程序(application)。基本上,**記憶管理分配的是虛擬記憶(virtual memory)而不是物理記憶體**,而物理記憶則是RAM中的實際地址空間。不要混淆物理記憶和虛擬記憶。 > - 虛擬地址的分配克服了對物理記憶分配的限制。物理地址轉換為虛擬地址是由MMU(記憶管理單元)執行的,它提供了對記憶幹擾的保護、記憶共享和虛擬記憶的分配。物理地址空間被劃分為一些被稱為幀frame的內存塊block,每個幀 包含多個頁pages。 > > - Linux檔案系統: > - Linux 檔案系統是一個層次化結構的樹,組織檔案和目錄。 > - 根目錄(root)是主要目錄,只有超級用戶才能訪問,子目錄(Sub directory)則位於根目錄下,用戶可以創建或重新命名。 > - Linux 支持許多檔案類型,如 ext2、ext3、設備檔案、區塊檔案、網路檔案系統等。 > > 圖中的系統呼叫介面(The System Call Interface)則展示了核心如何提供這些功能給用戶空間的應用程序,並且核心子系統如何作為模組被實現,以支援與硬體的直接交互。 #### Linux Kernel 從功能面來看 ##### 系統資源管理 如前圖所述 - **程序調度 (Process Scheduling)** - **記憶體管理 (Memory Management)** ##### 硬體抽象層 - **硬體隔離 (Hardware Abstraction)**: 核心提供了一個抽象層,隔離了應用程序和實際硬體之間的直接互動。這意味著應用程序不需要針對特定硬體編寫代碼,增加了代碼的可移植性。 - **硬體資源分配 (Hardware Resource Allocation)**: 核心負責分配和管理各種硬體資源,如處理器時間、記憶體空間和I/O裝置。這確保了硬體資源的有效利用和衝突的最小化。 ##### 系統安全與穩定性 - **權限控制 (Permission Control)**: 核心通過用戶和群組權限來控制對檔案、網路資源和其他系統資源的訪問。這是系統安全的關鍵部分,防止未授權的訪問和操作。 - **錯誤處理 (Error Handling)**: 核心負責監控系統的整體健康狀態,並處理來自硬體和軟體的錯誤。這包括從簡單的應用程序崩潰到嚴重的硬體故障的處理。 Linux核心作為操作系統的核心,扮演著管理和協調硬體與軟體資源的關鍵角色。它的設計旨在提供穩定、高效和安全的運行環境。 #### Kernel設計原則 Linux 的設計原則與核心模組(Kernel modules)含四個主要元件,這些元件協同工作以支援系統的彈性與功能性: 1. **模組管理系統 (module-management system)**: - 負責管理核心內的模組,例如加載、卸載模組,並處理模組間的依賴關係。 2. **模組加載和卸載程式 (module-loader and unloader)**: - 允許在核心運行時動態加載或卸載模組,這增加了系統的靈活性並允許即時更新功能。 3. **Driver程式註冊系統 (driver-registration system)**: - Driver程式是核心與硬體之間的中介,這個系統負責 確定核心可以正確與硬體通信,並處理硬體相關的事件和中斷。 4. **衝突解決機制 (conflict-resolution mechanism)**: - 確保當多個模組或Driver試圖訪問相同資源時,可以有效解決衝突,保持系統穩定運行。 Linux 的核心設計遵循模組化原則,這使得系統具有高度的擴展性和自定義能力。核心模組可以按需加載,無需重新編譯整個核心,這為硬體支持和新功能的整合提供了便利。這種設計允許 Linux 核心在不同的硬體和使用情境下運行,同時也使得社群和開發者可以相對容易地為核心貢獻或定制模組。 除了核心模組系統,Linux 核心還包括了如處理器調度、記憶體管理、檔案系統、網路堆疊等多種內建功能,這些都是以模組的形式或是核心的一部分實現,以支持從嵌入式設備到大型伺服器的多種運行環境。 ## Boot Sequence (開機流程) | ![image](https://hackmd.io/_uploads/B1e8Ntaida.png =250x) | ![image](https://hackmd.io/_uploads/BkaIFTiuT.png =350x) | |:-------------------------------------------------------------------------------------------------------------:|:------------------------------------------------------------------------------------------------------------------ | | [6 Stages of Linux Boot Process (Startup Sequence)](https://www.thegeekstuff.com/2011/02/linux-boot-process/) | [Linux: Understanding the boot process](https://www.enablegeek.com/tutorial/linux-understanding-the-boot-process/) | ![image](https://hackmd.io/_uploads/BktUf_gj6.png =600x) > [Image Credit: Mahesh Mallikarjunaiah](https://www.linkedin.com/in/maheshma/) ![image](https://hackmd.io/_uploads/rkn5IZ55T.png =600x) > [2023.01。。Linux Boot Process Explained Step by Step in Detail](https://www.golinuxcloud.com/linux-boot-process-explained-step-detail/) 開機流程是Linux系統啟動的一系列步驟,從加電到系統完全啟動。 ### 1. BIOS (Basic Input Output System)階段 ![image](https://hackmd.io/_uploads/rkdn8Zqca.png =600x) 電腦開機時,BIOS 是第一個被調用的程序,用於檢查機器中的硬件是否存在並且功能正常 - **功能**: BIOS(基本輸入輸出系統)或UEFI(統一可擴展韌體介面)是開機流程的第一步。當按下電源按鈕時,CPU會查找ROM中的指令。 - **系統檢查與啟動裝置尋找**: BIOS/UEFI首先進行系統完整性檢查,然後尋找引導裝置,如硬碟、光碟或USB裝置。 - 電腦啟動時,BIOS (Basic Input/Output System) 會進行硬體檢查,稱為開機自我測試 (Power-on Self Test, POST),然後從設定的啟動設備中尋找啟動扇區 ### 2. MBR(Master Boot Record, 主要開機記錄區)階段 :pencil: 一小段程式碼,負責加載作業系統 ![image](https://hackmd.io/_uploads/H1CnObcqa.png =400x) ![image](https://hackmd.io/_uploads/SycCPZ9cT.png =400x) - **主引導記錄 (MBR)**: - 儲存在可啟動磁碟的第一個扇區 1st sector of the bootable disk - 佔用512位元組的空間它負責尋找並加載引導加載器 * 1st 446 bytes: boot loader info * next 64 bytes: partition table info * last 2 bytes: mbr validation check - 主引導記錄(MBR)包含了啟動程式碼和分區表。BIOS 將控制權交給 MBR,後者尋找啟動分區 - **啟動分區表(Partition Table)** - Partition flag:通常用於標示啟動分區(bootable partition) - Start CHS:起始柱面-頭-扇區(Cylinder-Head-Sector)地址,顯示分區的起始位置 - Partition type:分區類型字節,用於識別分區的文件系統類型或用途 - End CHS:結束柱面-頭-扇區地址,顯示分區的結束位置 - Start LBA:起始邏輯塊地址(Logical Block Addressing),以塊為單位的起始地址 - Size:分區大小,通常以扇區數量來表示。 ![image](https://hackmd.io/_uploads/B1f5O-q5a.png =600x) ![image](https://hackmd.io/_uploads/SJNy6ajdp.png =400x) > boot loader 安裝在 MBR, boot sector 與作業系統的關係 > 圖19.1.1、boot loader 安裝在 MBR, boot sector 與作業系統的關係 > - 每個作業系統預設是會安裝一套 boot loader 到他自己的檔案系統中 (就是每個 filesystem 左下角的方框),而在 Linux 系統安裝時可以選擇將 boot loader 安裝到 MBR 去,也可以選擇不安裝。 > - 如果選擇安裝到 MBR 的話,那理論上在 MBR 與 boot sector 都會保有一份 boot loader 程式的。 > - 至於 Windows 安裝時,他預設會主動的將 MBR 與 boot sector 都裝上一份 boot loader!所以, 會發現安裝多重作業系統時, MBR 常常會被不同的作業系統的 boot loader 所覆蓋 > [source: linux.vbird.org/linux_basic/centos7](https://linux.vbird.org/linux_basic/centos7/0110whatislinux.php) ### 3. Boot Loader 階段 (Boot Loader Stage)-引導加載器 (GRUB) 開機管理程式 ![image](https://hackmd.io/_uploads/HJUNKZ556.png =600x) - 如果系統上安裝了作業系統,則會安裝引導加載器。 - 常見的兩種引導加載器包括: - LILO (Linux Loader) - GRUB (Grand Unified Boot Loader) - 初始化設備並載入`initrd/initramfs` - 引導加載器會向用戶展示一個菜單列表,每個菜單項對應不同的作業系統。引導加載器接著開始引導作業系統。當選擇啟動 Linux 時,它會在記憶體中解壓縮 Linux 核心。 - 之後,選擇啟動的 Linux 核心會加載 `initrd (Initial ramdisk)`。`initrd` 被 Linux 核心用作記憶體中的臨時文件系統。 - 它包含了工具和核心模組,這些都是繼續引導過程所需的,包括暫時掛載一個虛擬根文件系統 - 根據GRUB配置檔案(`grub.conf`)中的“`root=`”指令掛載根檔案系統 - 有些 Linux 文件系統不使用 `initrd`,而是使用 `initramfs`,它是 `initrd` 的後繼者。 - `linuxrc` : 可執行文件 - 探測大容量儲存硬體並找到合適的核心模組來驅動大容量儲存硬體 - 這是為了準備實際的根文件系統被 Linux 核心掛載所必需 - **GRUB的角色** - GRUB(Grand Unified Bootloader)是一個常見的引導加載器。它知道如何讀取檔案系統,並允許選擇不同的核心映像或修改核心設定,讓用戶選擇不同的作業系統或核心配置進行啟動。 - **配置文件**: GRUB的配置文件通常位於 `/boot/grub/grub.conf` - 一旦使用者選擇了作業系統,GRUB將會將控制權交給該作業系統的核心 ![image](https://hackmd.io/_uploads/BkOvRaidT.png) > 圖19.1.2、開機管理程式的選單功能與控制權轉交功能示意圖 > - 上圖所示, MBR 使用 Linux 的 grub2 這個開機管理程式,並且裡面假設已經有了三個選單, > - 第一個選單可以直接指向 Linux 的核心檔案並且直接載入核心來開機; > - 第二個選單可以將開機管理程式控制權交給 Windows 來管理,此時 Windows 的 loader 會接管開機流程,這個時候他就能夠啟動 windows 了。 > - 第三個選單則是使用 Linux 在 boot sector 內的開機管理程式,此時就會跳出另一個 grub2 的選單 > > [source: linux.vbird.org/linux_basic/centos7](https://linux.vbird.org/linux_basic/centos7/0110whatislinux.php) 接下來進入4與5的階段 ### 4.Kernal核心加載 ![image](https://hackmd.io/_uploads/SJlPtZ99p.png =600x) * Kernel根據`linuxrc`探測的結果找出可以掛載真正的根檔案系統(`/rootfs`) * 核心加載後,會掛載指定的根檔案系統,並初始化記憶體和裝置。此時,核心會運行`/sbin/init`程序,這是Linux核心運行的第一個process,具有Process ID(PID)1 * 核心在啟動時第一個後台process或daemon process * 所有其他後台daemon process都是從`/sbin/init` 產生的 * `/sbin/init` process會根據不同運行等級的配置來載入其他系統守護process ![image](https://hackmd.io/_uploads/Syz9tbqc6.png =300x) ### 5. Init與運行級別 - **Init的作用**: Init根據 `/etc/inittab` 文件設定的運行級別來初始化系統。 - **運行級別**: Linux系統有多個運行級別,從0(關機)到6(重啟),以及單用戶模式和多用戶模式。 - 核心執行 /sbin/init 程序(在使用 systemd 的系統中,該程序會被 systemd 取代),這是系統初始化的第一個程序。 ### 補充鳥哥網站中的細節說明 :::info - **Boot Loader (啟動載入器)**: - 對應上述BIOS將控制權交給**2. MBR**啟動程式碼和分區表,MBR尋找並執行GRUB - 接著,**3. GRUB**(或其他引導加載器)作為啟動管理器,讓用戶選擇不同的操作系統或核心配置來啟動 - boot loader 主要的功能如下: * 提供選單:使用者可以選擇不同的開機項目,這也是多重開機的重要功能! * 載入核心檔案:直接指向可開機的程式區段來開始作業系統; * 轉交其他 loader:將開機管理功能轉交給其他 loader 負責。 - **Kernal的偵測** - GGRUB加載核心之後,核心開始偵測並初始化硬體,這對應到**4.Kernel階段** - initramfs是Kernal的一部分,它在早期的啟動過程中提供必要的Driver和工具,以便核心能掛載真正的根文件系統,這個過程對應到**5.Init階段**,並以init程序(在systemd系統中是systemd程序)來完成系統的初始化和服務啟動 - 最後的 Runlevel 階段(或使用systemd的目標[target]) - 在開機流程的最後部分,負責啟動所有必要的服務,並不在此圖中顯示。在systemd系統中,runlevel被targets取代,負責定義系統應該達到的狀態或模式。 ::: :::success ![image](https://hackmd.io/_uploads/BJeybr9up.png) [source: linux.vbird.org/linux_basic/centos7](https://linux.vbird.org/linux_basic/centos7/0110whatislinux.php) 這張圖描繪了Linux 系統的詳細開機流程,可以與上述的六階段相對應。 - **BIOS階段**: - BIOS 初始化硬體設置並尋找啟動裝置中的啟動載入器,對應於上述的 BIOS 階段。 - **Boot Loader (啟動載入器)**: - 對應上述2. MBR(Master Boot Record, 主要開機記錄區)使用3. 導加載器 (GRUB) 開機管理讓用戶選擇不同的作業系統或核心配置進行啟動, - 啟動載入器,如 GRUB,被加載,用戶可以選擇不同的作業系統或核心配置,對應於上述的 GRUB 階段。 - **Kernel (核心)**: - 核心被載入記憶體,開始初始化過程,對應於上述的 Kernel 階段。 - **initramfs (初始 RAM 磁碟)**: - initramfs 是一個臨時的根文件系統,載入到記憶體中,並被用於支持核心的初始化過程,如載入必要的Driver程序。 - **Switch_root 到真實的根文件系統**: - 從 initramfs 切換到實際的根文件系統,這個過程在圖中未明確顯示,但它是連接 initramfs 和執行 init 過程的橋樑。 - **init/systemd 階段**: - 這是 init 階段的現代替代,systemd 被執行,開始啟動和管理系統服務,對應於上述的 Init 和 Runlevel 階段。 在這張圖中,initramfs 的功能是為核心提供一個臨時的根文件系統,讓它可以訪問磁碟上的文件系統。之後,系統會切換到真正的根文件系統,並啟動 systemd 或其他 init 系統,進入標準的運行等級或目標,完成開機過程。 ::: ### 6.Runlevel - **服務啟動**: 在Linux系統啟動過程中,會看到多個服務開始運行。這些服務是根據當前運行級別指定的目錄中的腳本啟動的。 - 系統根據預設的運行等級(runlevel)或目標(target),執行一系列的腳本或服務,完成啟動過程,並進入多用戶操作模式。 # Linux Kernel 架構 :::success - 學習目標: 1. 了解 Kernel 與 Driver 之間的關係 2. 了解 Device Tree 在 Linux 中,所扮演的角色及用途 ::: ## Driver(驅動程式) Driver是Linux核心的一部分,主要負責與硬體設備進行溝通,確保硬體能夠正確響應軟體指令。 1. **硬體Driver的功能與抽象** - 硬體Driver是專門為特定硬體(如網路卡、顯示卡)設計的代碼,允許操作系統控制和溝通這些硬體。 - 透過將硬體操作封裝在Driver中,應用程序無需直接與硬體互動,從而提高了系統的可移植性和安全性。 2. **Linux Kernel的Driver模塊化與框架** - Linux支持Driver的模塊化設計,允許在系統運行時動態地加載或卸載Driver,增加了系統的靈活性和定制能力。 - Linux Kernel的Driver框架將平台相關代碼與平台獨立代碼分離,使得Driver程式可以跨平台重用,降低了開發和維護的複雜度。 3. **Driver與核心的互動** - Driver程式與核心之間的緊密結合確保了硬體和軟件之間的高效溝通,並有效管理硬體資源,如記憶體分配和I/O操作。 - 這種互動不僅提高了效率,還增強了系統的安全性,保護系統免受不良Driver程式的影響。 :::success ![image](https://hackmd.io/_uploads/SylvyMAdT.png =300x) 上圖展示了應用程式層、驅動層和硬體層之間的交互關係,特別是在camera接口和video捕獲contex中 - **核心 (Kernel)**: - 圖中,「Kernel」沒有直接標出,但它實際上涵蓋了「Driver Layer」這一部分。在 Linux 系統中,核心包含了許多不同的驅動程式,這些驅動程式負責管理和與硬體裝置進行通信 - V4L2 Layer」是Kernel的一部分,它提供了一套統一的接口供應用程式訪問視頻捕獲功能。 - 「Camera Driver」、「CCDC Driver」和「Sensor or Decoder Driver」都是核心的模組,負責與特定的硬體設備交互。 這些驅動程式組成了核心的一部分,工作在核心空間(不同於用戶空間,即「Application Layer」)。核心空間提供了對硬體資源的直接訪問,而用戶空間則提供了執行應用程式所需的環境。 因此,圖中的「Driver Layer」即為「Kernel」在這個特定硬體和軟體互動架構中的位置。 - **驅動 (Driver)**: - 在圖中,驅動層包含 V4L2 (Video for Linux 2) 框架、相機驅動、CCDC (Charge Coupled Device Controller) 驅動和感測器或解碼器驅動。 - V4L2 框架為應用程式提供了一個統一的介面來存取視頻裝置。它是 Linux 核心的一部分,允許用戶空間應用程式通過標準 API 與硬體進行交互。 - 相機驅動、CCDC 驅動和感測器或解碼器驅動是硬體特定的驅動程式,負責直接與實際硬體裝置通信,並實現 V4L2 定義的操作。 - **Device Tree**: - 雖然 Device Tree 沒有在這張圖中直接顯示,但它是一種數據結構,通常在系統啟動時被核心使用,以描述非自我描述硬體(如 ARM 硬體)的組件和它們之間的關係。 - Device Tree 有助於核心了解和配置硬體,例如,確定哪些驅動需要加載、設定 GPIO 引腳、設定時鐘或描述感測器的特性等。 - 在這個情況下,Device Tree 可能會包含 OV2659 感測器和 AM437x CCDC 的配置信息,並將這些信息傳遞給相應的驅動程式,以便正確初始化和配置這些硬體組件。 ::: #### 應用程式-Kernel(Driver)-硬體互動 ![image](https://hackmd.io/_uploads/SyONKXB5T.png =400x) 這張圖展示了操作系統(特別是類Unix系統)中應用程序與硬體之間的交互層次結構。它從上到下分為用戶模式和Kernel模式,並進一步展示了各種系統組件及其之間的關係。 1. **用戶模式 (User Mode)**: - **應用程序 (Application)**: 這代表運行在用戶空間的程序,它們通過系統調用與Kernel模式中的資源交互。 2. **系統調用接口 (System Call Interface)**: - 當應用程序需要進行如打開文件、讀取網路數據等操作時,它們會發出系統調用。系統調用是一種允許用戶空間程序請求Kernel提供服務的機制。 3. **Kernel模式 (Kernel Mode)**: - **虛擬文件系統 (VFS)**: 提供一個統一的文件系統接口給用戶空間的應用程序,抽象了具體的文件系統細節。 - **緩衝區快取 (Buffer Cache)**: 用於緩存資料,以減少對磁盤讀寫的次數,提高效率。 - **網路子系統 (Network Subsystem)**: 處理網路通信的各個層面,從高層的 BSD 套接字到底層的 IP 協議。 4. **設備驅動 (Device Driver)**: - **字符設備驅動 (Character Device Driver)**: - 字符設備驅動是操作系統中用於管理那些以字符為單位進行數據傳輸的設備的一類驅動程序。與塊設備不同的是,字符設備不是以數據塊的形式進行讀寫,而是以字符流(或稱為字節流)的形式逐字節進行。這些設備通常支持順序訪問,不支持隨機訪問。以下是一些典型的由字符設備驅動管理的設備: - 鍵盤: 鍵盤驅動程序會捕捉鍵盤上每次按鍵的信息,並將其轉換成對應的字符或命令,供系統進一步處理。 - 串行端口: 串行通訊(如RS-232)使用串行端口進行數據傳輸,字符設備驅動負責管理數據的序列化和反序列化過程。 - 相機設備: 在某些情況下,相機設備可能通過字符接口來訪問,特別是當數據流處理類似於一連串單個的數據包時 - **塊設備驅動 (Block Device Driver)**: 管理那些以塊為單位進行數據傳輸的設備,如硬盤。塊設備的數據存取比字符設備的隨機和順序存取更高效 - **網路設備驅動 (Network Device Driver)**: 負責管理網路接口卡(NIC)等網路硬體,這些硬體負責數據包的物理傳輸。 5. **硬體 (Hardware)**: - **物理設備 (Physical Device)**: 這一層包含實際的硬體設備,比如CPU、內存、硬盤驅動器、網路卡等。這些硬體通過相應的設備驅動程序與操作系統交互 在這個模型中,當一個應用程序需要讀取一個文件時,它會發出一個系統調用。這個調用會被傳遞到Kernel模式下的VFS。VFS會決定使用哪個文件系統驅動程序來處理這次調用,然後該文件系統驅動程序會透過塊設備驅動程序與具體的硬體交互,並通過緩衝區快取與應用程序交換數據。 當涉及到網路通信時,應用程序會使用BSD套接字API來發出請求,該請求會通過網路子系統傳遞給網路設備驅動程序,然後由物理網路接口完成數據的發送和接收。 這個分層的模型是理解現代操作系統的關鍵,它不僅隔離了不同功能的復雜性,也提供了一個標準化的方法來擴展系統功能,比如添加新的硬體或文件系統支持。在嵌入式系統的開發中,理解這個模型尤為重要,因為開發者經常需要直接與硬體交互,並且可能需要編寫或修改設備驅動程序來滿足特定的系統需求。 --- # Device Tree (設備樹) ### 何謂Device Tree? :::info - 一種數據結構,用於描述系統中的硬體組件 - 允許Linux核心與硬體組件進行溝通 ::: ![image](https://hackmd.io/_uploads/HysQwuxoT.png =600x) > [source: wiki.dreamrunner.org。Linux Device tree ](https://wiki.dreamrunner.org/public_html/Embedded-System/Linux-Device-Tree.html) > * `Node name`: 代表硬體元件名稱 > * `Property name`: 節點屬性名稱,用來描述硬體的特定特性 > * `Label`: 標籤用來在 Device Tree 中提供一個可引用的錨點,允許在樹的其他地方引用該節點 > * `/`: Device Tree 的根節點 > * `node0@0`:根節點下的一個子節點,表示特定硬體元件。 ### Device Tree Hierarchy ![image](https://hackmd.io/_uploads/SJTN_dgiT.png) > [labs.dese.iisc.ac.in/embeddedlab。Device Tree and Boot Flow](https://labs.dese.iisc.ac.in/embeddedlab/device-tree-and-boot-flow/) > * 模組化設計: > * 通過 `.dtsi` 和 `.dts` 文件的分離,達到代碼重用和維護的簡化 > * SoC/Peripheral Level (.dtsi 檔案): > * 定義通用硬體配置,如 SoC 核心功能和周邊接口 > * 為不同的板級設計提供可重用的基礎描述 > * Board Level (.dts 檔案): > * 針對特定板級設計的定制描述 > * 包含 `.dtsi` 文件,並根據特定需求添加或修改配置 > * 包含和覆蓋(Inclusion and Overlaying): > * `.dts` 文件包含 `.dtsi` 文件,形成層次結構中的上層 > * 後定義的節點和屬性可以覆蓋或擴展先前的描述 ### Device Tree功能 Device Tree用於靜態描述設備及其相互連接,是一種編譯後的描述,作為Kernel的輸入。 1. **硬體描述與識別** - 設備樹以樹狀結構詳細描述系統中的硬體設備及其配置,包括設備的**屬性**和**參數**,提供了一種標準化的方法來**識別和描述硬體**組件。 2. **系統啟動時的作用** - 在系統開機過程中,**kernel讀取Device Tree來識別和配置硬體**,這是硬體初始化和驅動加載的關鍵步驟,設備樹提供了必要的配置信息,使核心能夠正確地設置和初始化硬體。 :::success ![image](https://hackmd.io/_uploads/ryUZTbCOa.png =300x) [Using Multiple DTs](https://source.android.com/docs/core/architecture/dto/multiple) - 在Linux系統啟動時,Device Tree與kernel的互動 圖中可見系統啟動時,Device Tree如何作為硬體配置信息的中介,並由引導加載程序加載並提供給Kernel以完成硬體的初始化和配置。 1. 多個 `.dtb` 文件代表不同的硬體配置(如HW #1, HW #2, HW #3 ... HW #N),其中每個 `.dtb` 文件對應於一種特定的硬體設置。 2. 引導加載程序(bootloader)負責在啟動過程中識別系統的硬體(如圖中的 "X" 標記處所示)。 3. 一旦硬體被識別,引導加載程序將選擇相應的 `.dtb` 文件並將其加載為設備樹(DT),這個選擇過程可能是基於硬體ID或者其他識別機制。 4. 設備樹(DT)隨後提供給Kernel,用於配置硬體。這個配置過程包括使用設備樹中的信息來初始化硬體設備,並將適當的驅動程序與物理硬體綁定。 5. 硬體配置完畢後,Kernel繼續其餘的啟動過程,並最終達到一個運行狀態,允許用戶空間的程序與這些已配置的硬體進行交互。 ::: 3. **與驅動程式的匹配關係** - 設備樹中的兼容屬性用於匹配和加載適合的驅動程式,確保硬體與相應驅動的正確配對。 - 驅動程式包含支持的設備識別符,用於與設備樹中的兼容屬性進行匹配,從而實現動態配置和驅動的正確加載。 ### Device Tree workflow during Boot ![image](https://hackmd.io/_uploads/BJulC-Cd6.png =400x) [2023。Embedded Shiksha。Device Trees in Linux ](https://www.linkedin.com/posts/embedded-shiksha-117534236_linux-devicetree-kernel-activity-7118890463155159040-3sVF/) > - 設備樹(Device Tree)在Linux中的工作流程 > 從硬體配置的描述(DTS)到操作系統啟動時的硬體識別和配置(Kernel)的過程。 > 1. **DTS (Device Tree Source)** > - **描述腳本 (Description Script)**:人類可讀的文件,它描述了硬體設備的配置信息。 > 2. **DTC (Device Tree Compiler)** > - **編譯器 (Compiler)**:DTS文件通過這個編譯器編譯,生成DTB文件。 > 3. **DTB (Device Tree Binary)** > - **二進制數據 (Binary Data)**:這是編譯後的二進制文件,包含了硬體設備的配置信息。 > - 被引導加載程序(Bootloader)從存儲介質中讀取(Carry),並加載到記憶體中。 > 4. **引導加載程序 (Bootloader)** > - 在Linux系統啟動過程中,引導加載程序將DTB傳遞(Pass)給Kernel。 > 5. **Kernel** > - 啟動時, kernel會對DTB進行查找(Look up)和解析,以識別硬體配置。 > - kernel還會進行硬體探測(probe),並根據DTB中的信息將驅動程序綁定到對應的硬體設備。 > > 這個流程確保Linux kernel能夠識別硬體,並加載適當的驅動程序來與之通信和控制,這對於嵌入式系統來說尤其重要,因為嵌入式系統的硬體配置可能會有很大的變化。這個機制使得在不同硬體平台之間移植Linux kernel成為可能,而不需要為每種硬體配置重新編寫 kernel代碼。 ## Linux Kernel、Driver(驅動程式)和Device Tree(設備樹)之間的關係 > > #### 案例 1: USB 鍵盤的識別和使用 > 1. **Kernel (核心)**: Linux Kernel包含USB支持的核心代碼,負責管理USB裝置的基本操作和通訊。 > 2. **Driver (驅動程式)**: USB鍵盤專用的驅動程式會與Kernel中的USB子系統互動,解釋來自鍵盤的信號並將其轉換為操作系統可以理解的輸入事件。 > 3. **Device Tree (設備樹)**: 在嵌入式系統中,Device Tree描述了USB控制器的硬體信息,並可能指明了連接到USB控制器的鍵盤的存在,使Kernel能夠正確地識別和配置USB控制器和鍵盤。 > > #### 案例 2: 網路卡的初始化和網路連接 > 1. **Kernel (核心)**: Kernel包含網路堆疊的核心代碼,負責處理網路數據包的傳輸和路由。 > 2. **Driver (驅動程式)**: 特定網路卡的驅動程式負責與該網路卡的硬體進行溝通,如發送和接收數據包。 > 3. **Device Tree (設備樹)**: 在嵌入式系統中,Device Tree描述了網路卡的硬體參數和連接方式,使Kernel能夠識別網路卡並使用適當的驅動程式進行初始化。 > > ### 案例 3: 嵌入式系統中的GPIO (通用輸入輸出) 控制 > 1. **Kernel (核心)**: Kernel提供了GPIO子系統,用於管理和控制GPIO引腳。 > 2. **Driver (驅動程式)**: 特定設備(如LED燈或按鈕)的驅動程式會使用Kernel的GPIO子系統來控制GPIO引腳的高低電平或讀取其狀態。 > 3. **Device Tree (設備樹)**: Device Tree描述了GPIO引腳的配置和分配,如哪些GPIO引腳被用於LED燈或按鈕,從而使Kernel能夠根據這些信息正確地配置GPIO子系統。 > --- # Nvidia Jetson Linux Compile、Build Image、Flash :::success 1. 完成 Ubuntu 20.04 的安裝 2. 完成相關 dependency library 與工具的安裝,含 GNU compiler 等 3. 完成 Nvidia Jetson 開發環境的架設(版本 35.3.1) 4. 完成 Nvidia Jetson Xavier 的 Linux image 編譯,並 Nvidia Development Kit 實際硬體上執行且正常開機至 Shell consol ::: ## 完成相關 dependency library 與工具的安裝,含 GNU compiler 等 - 安裝 GNU Compiler Collection (GCC) 和 G++ ```bash= sudo apt update sudo apt install build-essential ``` GCC編譯器(GNU Compiler Collection) 是 GNU 項目中的重要部分,提供了多種語言的編譯器。gcc 和 g++ 則是 GCC 中特定於 C 和 C++ 語言的編譯器。 - **GNU 編譯器集合(GCC)**: - GCC 是 GNU 項目的一部分,是一套程式語言編譯器,支援多種語言,如 C、C++、Objective-C、Fortran、Ada、Go 等。 - GCC 最初僅支援 C 語言,後來逐步擴充至其他語言。 - **gcc 與 g++**: - `gcc` 是 GCC 中的 C 語言編譯器 - `g++` 是 GCC 中的 C++ 語言編譯器。用於編譯 C++ 程式,並自動將 C++ 標準庫包含在編譯過程中。 - **gcc 與 g++ 的關係**: - 雖然 gcc 和 g++ 是 GCC 的不同部分,但共享相同的後端技術,在處理程式碼時使用相同的編譯器核心和最佳化技術。 - gcc 可以編譯 C++ 程式,但不會自動連接 C++ 標準庫;而 g++ 除了編譯 C++ 程式外,還會自動連接所需的庫。 ## 完成 Nvidia Jetson 開發環境的架設(版本 35.3.1) ### 完成 Nvidia Jetson Xavier 的 Linux image 編譯,並 Nvidia Development Kit 實際硬體上執行且正常開機至 Shell consol :::spoiler 詳細設置流程參照MP的[Jetson AGX Xavier BSP 開發整理](https://hackmd.io/@duchungk7/H1BGiDs4h) > > 如果為 NVIDIA Jetson 模組設計自定義載板,需要編輯設備樹並從源代碼重新編譯Kernel,以啟動載板。 > > module names and P-numbers 參考連結: https://docs.nvidia.com/jetson/archives/r35.3.1/DeveloperGuide/index.html > ![image](https://hackmd.io/_uploads/BJJk_L0_p.png) > > ### 1. Set up cross compilation in Ubuntu (設置交叉編譯) > 由於我們在主機上編譯 Jetson(ARM64 架構),而主機大多是 x86 架構,因此我們需要下載相應的編譯器並進行交叉編譯的設置。所有後續步驟都應該在 Ubuntu 18 和 20 上運行。 > > 查看 通用 toolchain 目前最新版本(此範例不使用): > http://releases.linaro.org/components/toolchain/binaries/ > > NVIDIA 提供的 JetsonLinuxToolchain(使用此toolchain): > https://docs.nvidia.com/jetson/archives/r35.1/DeveloperGuide/text/AT/JetsonLinuxToolchain.html > > #### STEP01: 下載 NVIDIA JetsonLinuxToolchain > https://developer.nvidia.com/embedded/jetson-linux > ![image](https://hackmd.io/_uploads/HyX-dUR_a.png) > ![image](https://hackmd.io/_uploads/S1_ZdUCOp.png) > ![image](https://hackmd.io/_uploads/BypWdICdp.png) > > 下載後,放入目錄: > ![image](https://hackmd.io/_uploads/SJIMuIC_6.png) ::: --- # Nvidia development kit的linux架構與Boot Sequence 過程 ## Jetson Software Architecture ![image](https://hackmd.io/_uploads/BJQWASAdp.png) ### Jetson Linux BSP(Board Support Package) #### Jetson Linux BSP 簡介 - **專為NVIDIA Jetson硬體設計**:Jetson Linux BSP是為Jetson系列如TX2、Xavier等專門開發的。 - **包含定制的LinuxKernel**:針對Jetson硬體進行了優化和調整,以提供更好的性能和穩定性。 - **集成多媒體處理和AI工具**:包括支持GPU加速的深度學習和圖像處理庫。 #### Jetson Linux BSP 與一般Linux架構差異 1. **硬體特定優化**: - Jetson Linux BSP為特定硬體(NVIDIA Jetson)設計,而一般Linux架構更為通用。 - 包括GPU加速、能源管理等針對性優化。 2. **深度學習和圖像處理集成**: - 直接整合了TensorRT、cuDNN等AI和圖像處理庫,一般Linux則需另行安裝。 - 為AI和電腦視覺應用提供即用型工具和庫。 3. **多媒體和視頻處理強化**: - 強化的GStreamer、V4L2支持,專為高效視頻處理設計。 - 一般Linux可能需要額外配置和優化來達到相同的多媒體處理能力。 4. **嵌入式系統特有的特性**: - 包括低功耗運行、記憶體和存儲優化。 - 一般Linux更多聚焦於桌面或服務器環境,不特別針對嵌入式系統優化。 5. **加速運算支持**: - 包括cuBLAS、cuFFT等加速運算庫,適用於高性能計算任務。 - 一般Linux發行版這些加速運算庫不是內建的。 ### [Understanding the Boot Flow Process](https://docs.nvidia.com/drive/drive_os_5.1.6.1L/nvvib_docs/index.html#page/DRIVE_OS_Linux_SDK_Development_Guide/Bootloader/bootloader_bootflow.html) ![image](https://hackmd.io/_uploads/S1A7EURdT.png=400x) ![image](https://hackmd.io/_uploads/rJUVNL0da.png =500x) Jetson的啟動過程與標準Linux系統有所不同,尤其是在初始階段。以下是Jetson啟動流程的簡化描述: ### Jetson 啟動流程 #### 階段 1: 啟動ROM(BootROM) - **電源開啟後**,Tegra芯片上硬線的BootROM首先執行。 - BootROM初始化必要的寄存器以訪問所需的啟動媒介。 - 使用**BR_BCT**(Boot Configuration Table)來確定MB1的存儲位置、入口點和加載地址。 - BootROM加載並驗證MB1映像的合法性。 #### 階段 2: 微啟動1(Microboot 1,MB1) - 接管從BootROM的控制,進一步初始化系統。 #### 階段 3: 微啟動2(Microboot 2,MB2) - 繼續系統初始化並加載BPMP韌體(BPMP-FW)。 #### 階段 4: 韌體驗證(Dual Authentication of Firmware) - 系統進行韌體的雙重驗證以確保安全性。 #### 階段 5: 安全作業系統(SecureOS) - 如果配置了安全OS,則在此階段加載。 #### 階段 6: 監視器和虛擬機(Hypervisor and Virtual Machines) - 啟動Hypervisor,並可能初始化一或多個虛擬機。 ### 與標準Linux啟動過程的比較 在傳統的Linux啟動過程中,六個階段通常是: 1. BIOS/UEFI階段 2. Bootloader階段(如GRUB) 3. 核心加載階段 4. 初始化階段(init) 5. 系統初始化階段(Initrd/Initramfs) 6. 使用者空間階段(Userland) Jetson的啟動流程是為了支持其硬體架構特別設計的,包括BootROM、MB1、MB2等專有元件,這些在標準Linux啟動過程中是看不到的。而標準Linux啟動流程更加側重於軟件層面,與硬體結合程度較低。Jetson啟動流程在硬體層面上做了更多的工作,特別是在安全性和驗證方面,以適應其高性能和安全要求的嵌入式環境。 --- ## 參考資料 * https://linux.vbird.org * https://ubuntu.com * https://www.kernel.org - https://labs.dese.iisc.ac.in/embeddedlab/device-tree-and-boot-flow/ - https://hackmd.io/@combo-tw/Linux-%E8%AE%80%E6%9B%B8%E6%9C%83/%2F%40combo-tw%2FByYcRZjMr #### 編譯、燒錄相關 - [Linux Kernel Teaching](https://linux-kernel-labs.github.io/refs/heads/master/index.html) - [Jetson AGX Xavier BSP 開發整理](https://hackmd.io/@duchungk7/H1BGiDs4h) - [鳥哥。Linux 核心編譯與管理](https://linux.vbird.org/linux_basic/centos7/0540kernel.php) - [NVIDIA Jetson Linux 35.3.1](https://developer.nvidia.com/embedded/jetson-linux-r3531) - [Nvidia。Kernel Customization](https://docs.nvidia.com/jetson/archives/r35.3.1/DeveloperGuide/text/SD/Kernel/KernelCustomization.html) - [ridgerun。How to build NVIDIA a Jetson Xavier NX Kernel](https://developer.ridgerun.com/wiki/index.php/Jetson_Xavier_NX/Development/Building_the_Kernel_from_Source) - [Nvidia Jetson TX2 — build kernel & flash image](https://ttyusb0978.medium.com/nvidia-jetson-tx2-build-kernel-flash-image-acf221b6b2ff) - [2023.01。How to rebuild kernel for Jetson Linux 35.2.1](https://forums.developer.nvidia.com/t/how-to-rebuild-kernel-for-jetson-linux-35-2-1/243841)