linux 啟動流程?

linux 啟動流程

CPU 上電后最先執行的啟動代碼,通常確實是放在 arch 目錄下對應架構的啟動文件里。這是因為啟動代碼強相關于 CPU 架構和硬件細節,不同架構差異非常大。


具體說明

1. 為什么啟動代碼放在 arch 目錄?

  • 啟動代碼要設置 CPU 狀態(如寄存器、MMU、異常向量表等)。
  • 各架構 CPU 啟動流程不一樣,匯編語言代碼也差別大。
  • 所以放在 arch/架構名/boot/ 或類似目錄,便于管理。

2. 以常見架構為例

架構啟動代碼位置示例說明
x86arch/x86/boot/包含 real mode 到 protected mode 切換等代碼
ARMarch/arm/boot/包含內核入口匯編、initrd搬移等代碼
ARM64arch/arm64/kernel/head.S64位 ARM 啟動匯編代碼
MIPSarch/mips/kernel/MIPS 啟動相關代碼

3. 啟動流程簡述

  • CPU 上電后,會跳轉到一個固定的物理地址(Reset Vector)。
  • 該地址對應的代碼就是架構相關的啟動代碼,一般就是 arch/.../boot/... 里的匯編。
  • 啟動代碼初始化最基本的硬件,設置內存和CPU狀態。
  • 然后跳轉進入 C 語言編寫的內核入口函數 start_kernel()

總結

  • CPU 上電后的第一段執行代碼一定是架構相關的啟動代碼,放在 arch 目錄下。
  • 這是因為啟動時的硬件初始化和上下文設置緊密依賴 CPU 架構。
  • 通用內核代碼則放在 kernel/mm/fs/ 等目錄。

核心原因是內核啟動前后環境差異巨大,必須用匯編代碼做早期硬件和處理器環境初始化,才能安全可靠地進入 start_kernel

Linux 內核源碼里的 arch/ 目錄是 不同 CPU 架構相關代碼的匯總目錄


具體解釋

1. Linux 內核支持多種 CPU 架構

  • 比如 x86、ARM、MIPS、PowerPC、RISC-V 等。
  • 每種架構底層硬件接口和啟動流程差別很大。
  • 因此,內核源碼會根據架構分目錄管理。

2. arch/ 目錄的作用

  • arch/ 目錄下每個子目錄對應一個 CPU 架構,比如:
arch/├── x86/      # x86 架構相關代碼├── arm/      # 32位 ARM 架構代碼├── arm64/    # 64位 ARM 架構代碼├── mips/     # MIPS 架構代碼├── riscv/    # RISC-V 架構代碼...
  • 每個目錄里包含啟動匯編、CPU相關驅動、體系結構專屬的調度、內存管理、異常處理等代碼。
  • 其他跟架構無關的內核通用代碼則在 kernel/mm/fs/ 等目錄。

詳細解釋

1. CPU 上電后環境非常“原始”

  • CPU 剛上電時,只處于物理地址模式,沒有開啟分頁(虛擬內存)
  • 寄存器值不確定
  • 堆棧、內存布局未初始化
  • 特權級和CPU模式尚未設置

此時無法直接跳轉執行復雜的C代碼,因為C代碼依賴于正確的棧、數據段和運行環境。


2. 匯編入口(_start)做的事情

匯編代碼位于內核最開始的入口,做以下關鍵工作:

  • 設置 CPU 特權級(例如切換到內核態)
  • 配置段寄存器、堆棧指針
  • 設置分頁機制(啟用虛擬內存)
  • 清理未初始化的BSS段
  • 設置全局指針、數據指針等CPU寄存器
  • 關閉中斷或做其他硬件相關初始化

這些操作都只能用匯編完成,因為C環境尚未準備好。


3. start_kernel 的前提

start_kernel() 是用 C 語言寫的,它假設運行環境已經穩定

  • 棧已初始化
  • 全局變量可以正常訪問
  • CPU 處于正確模式
  • 內存管理子系統已部分就緒

換句話說,start_kernel 是“內核的真正入口”,但不是“CPU的入口”。


4. 總結

階段作用為什么不能直接跳到 start_kernel
CPU 上電 → _start 匯編初始化 CPU 寄存器、棧、分頁、特權級需要底層硬件初始化,C代碼依賴這些,直接跳C會崩潰
_startstart_kernel進入內核 C 語言環境,啟動內核子系統需要完整運行環境,匯編做的準備工作必須先完成

簡單比喻

匯編入口相當于“內核啟動的引導員”,負責把環境布置好;
start_kernel 是“內核真正的司機”,環境準備好了才上車啟動。


好的,講講 secondary_start_kernel 的作用和背景。


什么是 secondary_start_kernel

  • 它是 Linux 內核在多核(SMP)系統中,非主CPU(Secondary CPU) 啟動時的入口函數。
  • 主CPU(CPU0)執行 start_kernel 來啟動整個系統和初始化多核環境。
  • 其他CPU啟動后,會跳到 secondary_start_kernel,完成自己的初始化流程。

為什么需要 secondary_start_kernel

  • 多核CPU啟動時,只有主核(CPU0)從復位向量啟動,執行完整的內核啟動流程。
  • 其他核處于停頓狀態,需要被喚醒,并單獨執行一套簡化的初始化。
  • 這些核不會執行 start_kernel,而是執行 secondary_start_kernel,完成自己的CPU初始化和進入調度。

secondary_start_kernel 主要做什么?

  • 初始化該CPU的本地數據結構(如CPU寄存器、TSS、IDT等)
  • 設置該CPU的中斷和調度環境
  • 把該CPU加入到內核的調度器中,開始運行任務
  • 不重復執行主核完成的系統全局初始化

簡單流程示意

主核 (CPU0) 啟動 -> 執行 start_kernel -> 初始化系統 -> 喚醒其他核
其他核 (CPU1..N) 啟動 -> 執行 secondary_start_kernel -> 初始化本地CPU環境 -> 進入調度循環

位置與調用

  • secondary_start_kernel 通常定義在 init/main.c
  • 各架構啟動匯編在喚醒其他CPU時會跳轉到這個函數
  • 是 SMP 初始化的關鍵環節

總結

函數名作用適用CPU
start_kernel主核啟動,系統初始化CPU0(主CPU)
secondary_start_kernel非主核啟動,局部CPU初始化和進入調度其他CPU(輔助CPU)

好的,下面詳細介紹 initrd 在 ARM 和 x86 Linux 內核啟動流程中的具體實現細節,幫助你理解它是怎么工作的。


一、initrd 的啟動流程核心概念

  • initrd 是內核啟動時內存中的一個臨時根文件系統映像。
  • 內核啟動時先掛載它作為根文件系統,執行初始化工作,之后切換到真實根文件系統。
  • 在啟動參數中通過內核命令行參數或 bootloader 傳遞 initrd 的位置和大小。

二、x86 啟動流程中的 initrd

1. Bootloader 階段

  • Bootloader(如 GRUB)加載內核鏡像 vmlinuz 和 initrd 鏡像到內存。
  • 將 initrd 起始地址和大小放入內核啟動參數(例如內核命令行中的 initrd=0x地址,大小)。
  • 將控制權交給內核。

2. 內核啟動匯編階段

  • arch/x86/boot/header.S 等文件,內核啟動匯編代碼初始化后,會調用內核的 C 入口 start_kernel()
  • 內核解析啟動參數,獲得 initrd 地址和大小。

3. 內核 C 語言初始化階段(init/do_mounts.c

  • 內核根據啟動參數調用 setup_initrd()(2.6 內核及類似版本)。
  • setup_initrd() 負責把 initrd 映像注冊為臨時塊設備(ramdisk),并掛載為根文件系統(initrd rootfs)。
  • 調用 initrd 內部的 /init 程序進行系統初始化。

4. 切換到真實根文件系統

  • 初始化完成后,pivot_root()switch_root() 將根文件系統切換到硬盤或其他設備的文件系統。
  • initrd 被卸載,內核開始正常運行用戶空間系統。

三、ARM 啟動流程中的 initrd

1. Bootloader 階段

  • Bootloader(如 U-Boot)將內核鏡像(zImage/uImage)和 initrd 加載到內存。

  • U-Boot 通過寄存器(如 r0-r3)傳遞內核啟動參數:

    • r2 寄存器通常保存 initrd 的起始地址。
    • r3 寄存器保存 initrd 大小。
  • 設備樹(DTB)也可能攜帶 initrd 信息。

2. ARM 匯編入口階段 (arch/arm/boot/bootp/init.S 等)

  • 內核啟動匯編代碼讀取這些參數,做內存搬移(前面你看過的 init.S 代碼就是搬移 initrd 的例子)。
  • 將 initrd 拷貝到合適內存區域,確保后續內核使用。

3. 內核 C 入口 (start_kernel)

  • 解析傳入的 initrd 地址和大小,調用 setup_initrd()
  • initrd 作為臨時根文件系統掛載。
  • 執行 initrd 內部初始化腳本。

4. 切換根文件系統

  • 跟 x86 類似,切換到真實根文件系統,完成啟動。

四、內核中與 initrd 相關的關鍵函數

  • setup_arch():在架構相關初始化時調用,解析啟動參數,設置 initrd 信息。
  • setup_initrd():注冊并掛載 initrd,準備臨時根文件系統。
  • mount_root():掛載根文件系統時優先使用 initrd,后續切換根。
  • pivot_root() / switch_root():實現根文件系統的切換。

五、簡要總結流程圖

Bootloader 加載內核和 initrd --> 內核啟動匯編(解析initrd參數,搬移initrd) --> start_kernel(調用setup_initrd,掛載initrd) --> 執行initrd內的/init程序初始化 --> 切換到真實根文件系統(硬盤/網絡文件系統等)

六、相關文件位置(Linux 源碼)

功能典型源碼路徑
ARM 啟動匯編arch/arm/boot/bootp/init.S
x86 啟動匯編arch/x86/boot/header.S
initrd 處理init/do_mounts.cinit/do_mounts.h
根文件系統掛載fs/namespace.c

當然可以,下面是將你提供的 Linux 啟動流程(包括 Bootloader、主核、從核、initrd、根文件系統切換等)融合成的一個 Mermaid 序列圖


? Mermaid 序列圖(Linux 多核啟動流程 + initrd 啟動)

Bootloader主核(CPU0)其他核(CPU1..N)Linux 內核initrd(臨時根文件系統)真實根文件系統上電,跳轉內核入口(arch/.../head.S)執行 start_kernel()初始化內核子系統(時鐘、中斷、內存、調度器等)喚醒其他核(SMP)執行 secondary_start_kernel()初始化 CPU 本地環境,進入 idle/sched 循環解析內核參數,包括 initrd調用 setup_initrd()解壓并掛載 initrd執行 initrd 中的 /init 程序完成系統初始化邏輯(例如掛載 dev tmpfs)切換到真實根文件系統(硬盤/網絡等)執行 /sbin/init(或 systemd)系統啟動完成,進入用戶空間Bootloader主核(CPU0)其他核(CPU1..N)Linux 內核initrd(臨時根文件系統)真實根文件系統

📌 說明

  • CPU0 是主核,從入口跳入 start_kernel,控制整個啟動過程。
  • CPU1..N 是從核,由主核在適當時機喚醒,執行 secondary_start_kernel
  • Bootloader 通常負責將內核、initrd 以及設備樹加載到內存,并設置參數。
  • initrd 是臨時根文件系統,內核通過參數掛載它,并執行其中的 /init
  • /init 會負責進一步初始化和掛載真實根文件系統(如 ext4、NFS 等)。
  • 最終系統進入真實根文件系統的 /sbin/init,開始正常運行。

本文來自互聯網用戶投稿,該文觀點僅代表作者本人,不代表本站立場。本站僅提供信息存儲空間服務,不擁有所有權,不承擔相關法律責任。
如若轉載,請注明出處:http://www.pswp.cn/diannao/94031.shtml
繁體地址,請注明出處:http://hk.pswp.cn/diannao/94031.shtml
英文地址,請注明出處:http://en.pswp.cn/diannao/94031.shtml

如若內容造成侵權/違法違規/事實不符,請聯系多彩編程網進行投訴反饋email:809451989@qq.com,一經查實,立即刪除!

相關文章

《Kubernetes部署篇:基于Kylin V10+ARM64架構CPU使用containerd部署K8S 1.33.3集群(多主多從)》

總結:整理不易,如果對你有幫助,可否點贊關注一下? 更多詳細內容請參考:企業級K8s集群運維實戰 一、架構圖 如下圖所示: 二、環境信息 基于x86_64+aarch64架構使用containerd部署K8S 1.33.3集群資源合集(三主多從) 2、部署規劃 云平臺 主機名 K8S版本 系統版本 CPU架構…

Docker 鏡像打包為 ZIP 文件便于分享和轉發

網上找到的記錄一下方便下次看步驟詳解1. 將鏡像導出為 TAR 文件Docker 提供了 docker save 命令,可以將鏡像導出為 .tar 文件。使用以下命令:docker save -o dify.tar dify說明:docker save:導出鏡像為文件。-o dify.tar&#xf…

一對一交友小程序 / APP 系統架構分析

一對一交友小程序 / APP 系統架構分析一、引言在數字化社交的大背景下,一對一交友小程序和 APP 為人們拓展社交圈提供了便捷途徑。合理且高效的系統架構是保障此類應用穩定運行、提升用戶體驗的基石。本文將深入剖析一對一交友小程序 / APP 的系統架構,涵…

Anthropic最新研究Persona vector人格向量

今天本來就想更一期強化學習,但是突然看了Anthropic的persona vector,所以又來寫這一篇,因為我覺得這個很有價值以往我們玩LLM比較怕的事就事他亂說話作為概率模型,它能說對,它也能亂編,亂編輕癥就是所謂的…

Spring AI集成Elasticsearch向量檢索時filter過濾失效問題排查與解決方案

使用vectorStore.similaritySearch遇到問題 最近需要做一個功能,用到了es做向量數據庫。在使用vectorStore.similaritySearch查詢的時候,發現filterExpression中加的條件并沒有完全生效,導致查詢出來的數據不準確,出現了不符合me…

安燈系統(Andon System)

安燈系統是源自豐田生產系統(TPS)的一種可視化生產管理工具,其名稱"Andon"來自日語的"提燈",原指用于報警的燈籠,現已成為制造業現場管理的核心工具之一。一、安燈系統的定義安燈系統是一種實時監控生產異常的可視化管理…

MyBatis與MySQL

要理解 MyBatis 語法及其與 MySQL 的區別,首先需要明確兩者的本質定位:MyBatis 是 Java 的持久層框架(負責 Java 對象與數據庫數據的映射),而MySQL 是關系型數據庫管理系統(負責數據的存儲和 SQL 執行&…

Vulnhub Noob靶機復現(附提權)

一、安裝靶機 下載地址:https://download.vulnhub.com/noob/Noob.ova 下載好后使用VM打開配置如下。 二、主機發現 使用nmap掃描確認靶機ip(192.168.29.138) nmap -sn 192.168.29.1/24 三、端口掃描 使用nmap工具掃描全部端口以防遺漏。 nmap -A -p- 192.168.…

文心4.5開源測評:國產大模型的輕量化革命與全棧突破

> 當算力成本成為AI落地的最大攔路虎,一款僅需2.1GB顯存、支持32K上下文的輕量級大模型如何撬動產業智能化的大門? ^ - ^ 2025年6月30日,百度正式開源文心大模型4.5系列,以**10款全維度模型矩陣**(0.3B至424B參數)刷新國產開源模型的技術邊界。這不僅是參數規模的躍進…

【自存用】mumu模擬器+mitmproxy配置

一、 安裝證書 下載mitmproxy進行安裝。cmd 輸入 mitmdump產生證書在C:\Users\賬號名.mitmproxy找到mitmproxy-ca.p12,雙擊進入證書導入向導,一直點下一頁,直到選擇證書存儲的地方選擇【受信任的根證書頒發機構】,后面的繼續點【是】或【完成…

Java中的字符串 - String 類

在C語言中若要表示字符串只能使用字符數組或者字符指針,Java語言則專門提供了 String 類,在面向對象編程中具有重要地位。在開發和校招筆試中,字符串也是常客。 目錄 一、字符串的構造 二、常用方法 2.1 字符串的拼接 2.2 字符串之間的比…

[網安工具] Web 漏洞掃描工具 —— AWVS · 使用手冊

🌟想了解其它網安工具?看看這個:[網安工具] 網絡安全工具管理 —— 工具倉庫 管理手冊 Acunetix | Web Application Security ScannerAcunetix is an end-to-end web security scanner that offers a 360 view of an organization’s securi…

丑數-優先隊列/三指針/動態規劃

丑數 Solution 核心思路&#xff1a; 注意的幾個點&#xff1a; 1.優先隊列改變排序&#xff1a; priority_queue<int,vector<int>,greater<int>> q;2.用來判斷是否訪問過&#xff0c;可以用unordered_set 注意set的插入用的是insert而不是push unorder…

FPGA(或者數字電路)中組合邏輯和時序邏輯是怎么劃分的

1.組合邏輯 在FPGA中&#xff0c;組合邏輯是哪些沒有觸發器作為存儲單元的電路 LUT查找表就是組合邏輯電路&#xff0c;無時鐘信號參與。 加法器&#xff0c;邏輯門&#xff0c;多路選擇器&#xff0c;譯碼器2.時序邏輯電路 輸出依賴于當前輸入&#xff0c;還依賴于過去 觸發器…

【音視頻】WebRTC 中的RTP、RTCP、SDP、Candidate

一、RTP 1.1 RTP協議介紹 在 WebRTC 中&#xff0c;RTP&#xff08;Real-time Transport Protocol&#xff0c;實時傳輸協議&#xff09;是音視頻媒體數據傳輸的核心協議&#xff0c;負責實時數據的封裝、傳輸與解封裝&#xff0c;為實時交互提供時序、同步、分片重組等關鍵能…

accept函數及示例

這次我們介紹 accept 函數&#xff0c;它是 TCP 服務器用來接受客戶端連接請求的核心系統調用。1. 函數介紹 accept 是一個 Linux 系統調用&#xff0c;專門用于TCP 服務器&#xff08;使用 SOCK_STREAM 套接字&#xff09;。它的主要功能是從監聽套接字&#xff08;通過 liste…

【Java】在一個前臺界面中動態展示多個數據表的字段及數據

企業的生產環境中&#xff0c;如果不允許直接操作數據表中的數據&#xff0c;則需要開發一個前臺界面&#xff0c;在必要時實現對多個數據表中數據的增刪改查&#xff0c; 此時就需要后端將Oracle表字段及數據查詢返回前端動態展示…… 一、Oracle特定元數據查詢 使用JDBC獲取O…

MySQL(174)如何理解MySQL的多版本并發控制(MVCC)?

MySQL的多版本并發控制&#xff08;MVCC, Multi-Version Concurrency Control&#xff09;是一種用于實現高并發性的機制&#xff0c;它允許多個事務同時讀取和寫入數據&#xff0c;而不會相互阻塞。MVCC主要在InnoDB存儲引擎中實現&#xff0c;通過維護數據的多個版本來實現一…

Docker--將非root用戶添加docker用戶組,解決頻繁sudo執行輸入密碼的問題

一、為什么要有docker用戶組&#xff1f; 根本原因&#xff1a; Linux的設備訪問權限控制機制 Docker守護進程&#xff08;dockerd&#xff09;運行時會創建一個特殊的Unix套接字文件&#xff0c;如&#xff1a;/var/run/docker.sock。 這個文件就像一個“門”&#xff0c;所有…

C語言---函數的遞歸與迭代

遞歸的理解與限制條件 所謂函數遞歸就是遞推加回歸的過程&#xff0c;就是函數自己調用自己。遞歸的思想就是把復雜的問題拆分成與原來那個大問題相似的子問題來求解&#xff0c;大事化小&#xff0c;像剝洋蔥一樣&#xff0c;最終把問題解決。 遞歸的限制條件&#xff1a; 一個…