Linux 啟動過程流程圖--ARM版

以下是ARM版本Linux啟動過程的超詳細樹狀圖,涵蓋硬件上電到應用程序交互的全流程,并包含關鍵函數調用鏈及源碼位置,適用于系統開發與調試場景:

ARM Linux啟動全流程(含函數調用鏈)

ARM Linux啟動流程(函數級調用鏈)
│
├─── **1. 硬件上電與Boot ROM階段**
│   │
│   ├─── 硬件復位與初始化
│   │   ├─── CPU進入Reset異常向量(ARM異常向量表基址0x0或0xffff0000)
│   │   │   └─── 匯編代碼:arch/arm/kernel/entry-armv.S:reset_handler
│   │   │
│   │   ├─── 關閉Cache和MMU
│   │   │   ├─── 匯編指令:MCR p15,0,r0,c7,c5,0 ( invalidate icache)
│   │   │   └─── 匯編指令:MRC p15,0,r0,c1,c0,0; BIC r0,r0,#1 ( disable MMU)
│   │   │
│   │   └─── 初始化棧空間(SP指針)
│   │       └─── 匯編代碼:設置SVC模式棧,arch/arm/kernel/entry-armv.S
│   │
│   └─── Boot ROM固件(廠商固化,如ARM Trusted Firmware)
│       ├─── 加載Boot Loader到RAM
│       │   ├─── 從啟動設備(eMMC/SD卡)讀取U-Boot鏡像
│       │   └─── 復制鏡像到指定內存地址(如0x80000000)
│       │
│       └─── 跳轉執行Boot Loader
│           └─── 匯編指令:BX BootLoader入口地址
│
├─── **2. 引導加載程序階段(以U-Boot為例)**
│   │
│   ├─── Stage 1:匯編初始化(arch/arm/cpu/armv7/start.S)
│   │   ├─── 異常向量表初始化
│   │   │   └─── 定義Reset、Undefined、IRQ等異常處理入口
│   │   │
│   │   ├─── 內存控制器初始化
│   │   │   ├─── 配置DDR時序:arch/arm/cpu/armv7/mx6/sdram.c:mx6_sdram_initialize
│   │   │   └─── 初始化MMU頁表(臨時)
│   │   │
│   │   ├─── 串口初始化
│   │   │   ├─── 配置UART控制器:drivers/serial/serial.c:serial_initialize
│   │   │   └─── 設置波特率、數據位等參數
│   │   │
│   │   └─── 加載Stage 2到RAM
│   │       ├─── 從Flash/SD卡讀取U-Boot第二階段鏡像
│   │       └─── 跳轉執行:ldr pc, =stage2_entry
│   │
│   ├─── Stage 2:C代碼初始化(lib_arm/board.c:start_armboot)
│   │   ├─── 硬件設備初始化
│   │   │   ├─── 初始化NAND/SD卡:drivers/mtd/nand/nand_base.c:nand_init
│   │   │   ├─── 初始化USB:drivers/usb/usb_main.c:usb_init
│   │   │   └─── 初始化網絡:drivers/net/eth.c:eth_initialize
│   │   │
│   │   ├─── 設備樹解析
│   │   │   ├─── 讀取.dtb文件:drivers/of/fdt.c:fdt_init
│   │   │   └─── 驗證設備樹:drivers/of/fdt.c:fdt_validate
│   │   │
│   │   ├─── 加載Linux內核
│   │   │   ├─── 從存儲設備讀取內核鏡像:common/cmd_load.c:do_load
│   │   │   └─── 解壓縮內核(如zImage):lib/decompress.c:decompress
│   │   │
│   │   ├─── 傳遞啟動參數
│   │   │   ├─── 構建cmdline:board/arm/yourboard/yourboard.c:setup_args
│   │   │   └─── 設置啟動參數地址:arch/arm/lib/bootm.c:do_bootm_linux
│   │   │
│   │   └─── 跳轉啟動內核
│   │       └─── 匯編調用:arm/linux/bootm.c:bootm_linux
│   │
│   └─── 關鍵函數調用鏈
│       ├─── start_armboot()
│       │   ├─── board_init()
│       │   ├─── device_tree_init()
│       │   ├─── load_kernel_image()
│       │   └─── bootm_linux()
│
├─── **3. 內核初始化階段(kernel_init)**
│   │
│   ├─── 內核解壓縮與架構初始化(arch/arm/kernel/head.S)
│   │   ├─── 解壓縮內核鏡像(如zImage)
│   │   │   └─── 匯編解壓縮代碼:arch/arm/boot/compressed/head.S
│   │   │
│   │   ├─── ARM架構初始化
│   │   │   ├─── 配置頁表:arch/arm/mm/proc-v7.S:create_page_tables
│   │   │   ├─── 啟用MMU:arch/arm/mm/proc-v7.S:enable_mmu
│   │   │   ├─── 初始化GIC中斷控制器:drivers/interrupts/gic.c:gic_init
│   │   │   └─── 多核啟動:arch/arm/kernel/smp.c:smp_init
│   │   │
│   │   └─── 跳轉到C語言入口:start_kernel()
│   │       └─── 定義于init/main.c:start_kernel
│   │
│   ├─── 內核C語言初始化(init/main.c:start_kernel)
│   │   ├─── 調度器初始化:sched_init()
│   │   │   └─── kernel/sched/core.c:sched_init
│   │   │
│   │   ├─── 內存管理初始化:mm_init()
│   │   │   ├─── 伙伴系統初始化:mm/page_alloc.c:page_alloc_init
│   │   │   ├─── slab分配器初始化:mm/slab.c:kmem_cache_init
│   │   │   └─── 高端內存映射:mm/highmem.c:highmem_init
│   │   │
│   │   ├─── 設備模型初始化:device_tree_init()
│   │   │   ├─── 解析設備樹:drivers/of/fdt.c:of_platform_default_populate
│   │   │   ├─── 注冊平臺總線:drivers/base/platform.c:platform_bus_init
│   │   │   └─── 匹配設備與驅動:drivers/base/dd.c:driver_probe_device
│   │   │
│   │   ├─── 驅動子系統初始化:drivers_init()
│   │   │   ├─── 初始化PCI/USB總線:drivers/pci/pci.c:pci_subsystem_init
│   │   │   ├─── 注冊字符設備驅動:drivers/char/char_dev.c:register_chrdev
│   │   │   └─── 初始化塊設備:drivers/block/genhd.c:block_device_init
│   │   │
│   │   ├─── 文件系統初始化:filesystem_init()
│   │   │   ├─── 注冊ext4文件系統:fs/ext4/ext4_init
│   │   │   ├─── 掛載rootfs:fs/namespace.c:mount_root
│   │   │   │   ├─── 解析root=參數:fs/cmdline.c:parse_cmdline
│   │   │   │   └─── 調用具體文件系統mount函數
│   │   │   └─── 初始化tmpfs:fs/tmpfs/inode.c:tmpfs_init
│   │   │
│   │   ├─── 網絡子系統初始化:net_init()
│   │   │   ├─── 初始化TCP/IP協議棧:net/ipv4/af_inet.c:inet_init
│   │   │   ├─── 注冊網絡設備:drivers/net/ethernet/ethernet.c:register_netdevice
│   │   │   └─── 配置DHCP:net/ipv4/dhcpcd.c:dhcpcd_init
│   │   │
│   │   └─── 啟動init進程:kernel_thread(init_post, NULL, CLONE_FS)
│   │       └─── init_post()定義于init/main.c
│   │
│   └─── 設備驅動加載流程(以GPIO驅動為例)
│       ├─── 設備樹匹配:of_device_match_table
│       │   └─── drivers/gpio/gpiolib-of.c:of_gpiochip_add
│       │
│       ├─── 驅動注冊:platform_driver_register()
│       │   └─── drivers/base/platform.c:platform_driver_register
│       │
│       ├─── 設備探測:driver_probe_device()
│       │   └─── drivers/base/dd.c:driver_probe_device
│       │
│       └─── 硬件操作函數:gpio_request(), gpio_set_value()
│           ├─── drivers/gpio/gpiolib.c:gpio_request
│           └─── drivers/gpio/gpiolib.c:gpio_set_value
│
├─── **4. 用戶空間啟動階段(systemd流程)**
│   │
│   ├─── init進程啟動(PID=1,init/main.c:init_post)
│   │   ├─── 解析啟動參數,確定init程序(如/systemd)
│   │   ├─── 掛載系統文件系統:
│   │   │   ├─── mount -t proc proc /proc
│   │   │   ├─── mount -t sysfs sysfs /sys
│   │   │   └─── mount -t devtmpfs devtmpfs /dev
│   │   │
│   │   └─── 執行init程序:do_execve()
│   │       └─── 系統調用:kernel/sys.c:sys_execve
│   │
│   ├─── systemd主流程(src/core/main.c:main)
│   │   ├─── 解析命令行參數:parse_arguments()
│   │   ├─── 初始化日志系統:log_init()
│   │   ├─── 加載單元配置:load_unit_files()
│   │   │   ├─── 解析.target文件:src/core/unit.c:unit_load
│   │   │   └─── 構建依賴圖:src/core/dependency.c:resolve_dependencies
│   │   │
│   │   ├─── 啟動基本系統服務:
│   │   │   ├─── systemd-udevd.service:src/udev/udevd.c:main
│   │   │   ├─── systemd-journald.service:src/journal/journald.c:main
│   │   │   └─── systemd-networkd.service:src/network/networkd.c:main
│   │   │
│   │   ├─── 激活默認目標(如multi-user.target)
│   │   │   ├─── 解析.target依賴:src/core/unit.c:unit_activate
│   │   │   ├─── 并行啟動服務:src/core/job.c:job_execute
│   │   │   └─── 等待服務就緒:src/core/manager.c:manager_wait_for_dependencies
│   │   │
│   │   └─── 啟動登錄服務:
│   │       ├─── getty@.service:src/login/getty.c:main
│   │       └─── lightdm.service(圖形界面):src/lightdm/lightdm.c:main
│   │
│   └─── 函數調用鏈示例(啟動網絡服務)
│       ├─── systemd_main()
│       │   ├─── manager_load_unit()
│       │   ├─── unit_activate()
│       │   ├─── job_queue()
│       │   └─── exec_service() → 調用networkctl啟動網絡
│
└─── **5. 應用程序與系統交互(函數級)**│├─── 終端交互(Shell命令執行)│   ├─── 用戶輸入命令(如ls)│   │   └─── shell解析:bash/src/eval.c:eval_command│   ││   ├─── 執行程序:fork() + execve()│   │   ├─── fork系統調用:kernel/fork.c:do_fork│   │   └─── execve系統調用:kernel/exec.c:do_execve│   ││   └─── 程序運行:libc函數 → 系統調用│       ├─── printf() → write() → sys_write│       └─── open() → sys_open(定義于arch/arm/kernel/sys_arm.c)│├─── 設備訪問流程(以串口為例)│   ├─── 打開設備:fd = open("/dev/ttyAMA0", O_RDWR)│   │   └─── 系統調用:fs/open.c:do_sys_open│   ││   ├─── 配置參數:ioctl(fd, TCSETS, &termios)│   │   └─── 驅動處理:drivers/tty/serial/8250/8250.c:serial8250_ioctl│   ││   └─── 讀寫數據:read(fd, buf, len) / write(fd, buf, len)│       ├─── 系統調用:fs/read_write.c:vfs_read/vfs_write│       └─── 驅動處理:drivers/tty/serial/8250/8250.c:serial8250_read/serial8250_write│├─── 網絡應用交互(Socket編程)│   ├─── 創建Socket:sock = socket(AF_INET, SOCK_STREAM, 0)│   │   └─── 系統調用:net/socket.c:sys_socket│   ││   ├─── 綁定地址:bind(sock, &addr, len)│   │   └─── 系統調用:net/ipv4/af_inet.c:inet_bind│   ││   ├─── 監聽連接:listen(sock, backlog)│   │   └─── 系統調用:net/core/sock.c:sys_listen│   ││   └─── 數據收發:send(sock, data, len, 0) / recv(...)│       ├─── 系統調用:net/core/sock.c:sys_sendto/sys_recvfrom│       └─── 協議處理:net/ipv4/tcp.c:tcp_sendmsg/tcp_recvmsg│└─── 系統調用在內核中的處理(以ARM為例)├─── 用戶態陷入內核:SWI指令或SVC指令(ARMv8)│   └─── 異常向量:arch/arm/kernel/entry-armv.S:svc_entry│├─── 系統調用分發:│   ├─── 解析SWI號:arch/arm/kernel/call-sysv.S:sys_call│   └─── 查找系統調用表:arch/arm/kernel/sys_arm.c:sys_call_table│└─── 具體系統調用處理:├─── 如sys_open:fs/open.c:do_sys_open└─── 如sys_write:fs/read_write.c:sys_write

關鍵技術點與源碼映射

1. ARM啟動階段的函數調用核心
  • 異常向量處理:ARMv7的Reset異常處理在arch/arm/kernel/entry-armv.S中,通過reset_handler函數完成底層初始化。
  • U-Boot Stage1:匯編代碼位于arch/arm/cpu/armv7/start.S,核心函數start_armboot是Stage2的入口。
  • 內核架構初始化arch/arm/kernel/head.S中的__create_page_tables__enable_mmu是MMU啟用的關鍵函數。
2. 設備驅動加載的函數鏈
  • 設備樹解析drivers/of/fdt.c中的of_platform_default_populate會遍歷設備樹節點,為每個節點匹配驅動。
  • 驅動注冊與探測platform_driver_register注冊驅動時,會調用driver_probe_device,該函數會觸發驅動的probe函數(如gpiochip_probe)。
3. systemd啟動的關鍵函數
  • 單元加載src/core/unit.c中的unit_load負責解析.service.target文件,構建依賴關系。
  • 并行啟動src/core/job.c中的job_execute實現服務的并行啟動,通過fork()exec()執行具體服務程序。
4. 系統調用在ARM上的實現
  • 異常機制:ARM通過SWI(ARMv7)或SVC(ARMv8)指令從用戶態陷入內核,異常處理入口在arch/arm/kernel/entry-armv.S
  • 調用表映射:系統調用號通過arch/arm/kernel/sys_arm.c中的sys_call_table映射到具體處理函數,如sys_open對應do_sys_open

典型ARM平臺啟動差異(函數級)

平臺關鍵函數差異
樹莓派(RPi)額外固件層函數:bootcode.bin調用start.elf中的initialize_platform(),再加載U-Boot。
ARM64(AArch64)啟動流程使用arch/arm64/kernel/head.S,MMU配置函數為__enable_mmu,支持4級頁表。
嵌入式設備可能自定義啟動函數,如直接從NOR Flash加載內核,使用load_elf_image()替代U-Boot的do_bootm

通過以上樹狀圖,可清晰看到從硬件上電到應用程序的每一層函數調用關系,尤其適合系統開發人員調試啟動問題、優化啟動時間或開發定制化啟動流程。如需進一步分析某模塊的函數調用細節(如GIC中斷初始化、USB驅動探測流程),可提供具體方向進行深入展開。

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

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

相關文章

NVMe高速傳輸之擺脫XDMA設計6之系統架構設計

結合目前應用需求,以及前面基礎分析,確定IP應具有如下特色: (1) 通用性 前端數據采集系統基于 FPGA 開發。 一方面, 設備類型多, 使用的 FPGA型號各不相同, 需要實現的設計能夠在多種…

Mac homebrew 安裝教程

下載github安裝包 https://github.com/Homebrew/brew/releases/tag/4.5.8 下載安裝后 打開 安全里面允許安裝,就可以直接使用了

stm32hal模塊驅動(1)hpdl1414驅動

之前一直想用hpdl1414畫一塊手表,前面pcb測試板畫完沒空調試,最近剛好空出來時間,遂發下驅動。 這里簡單贅述hpdl1414的驅動原理:D0-D6負責數據輸入(ascii表后7位),A0,A1負責更改hpdl1414模塊顯…

從代碼學習深度強化學習 - TRPO PyTorch版

文章目錄 前言核心工具函數廣義優勢估計 (Generalized Advantage Estimation, GAE)案例一:TRPO 解決離散動作問題 (CartPole-v1)1. 環境初始化2. 網絡結構定義3. TRPO 智能體實現4. 訓練與可視化5. 訓練主程序與結果案例二:TRPO 解決連續動作問題 (Pendulum-v1)1. 環境與工具…

MySQL 升級到8.4版本的詳細指南

本指南詳細介紹了將 MySQL 升級到 8.4 版本的完整流程、注意事項和操作方法。 一、升級前準備 (3.1 Before You Begin) 在開始升級之前,必須仔細審閱本節信息并執行所有推薦的操作: 理解升級過程:了解升級期間可能發生的情況。請參閱第 3.4…

leetcode427.建立四叉樹

區間x0到x1和區間y0到y1都是左閉右開的 解題基本思路是先判斷當前矩陣是不是全0或全1,如果是就直接返回新建的一個節點值(矩陣的統一值,葉子節點),如果不是那就新建一個節點值,非葉并且左上右上左下右下四個方向上遞歸創建節點 /…

醫學+AI教育實踐!南醫大探索數據挖掘人才培養,清華指導發布AI教育白皮書

教育數字化浪潮正以前所未有的力度重塑高等教育格局。今年4月,為貫徹落實《教育強國建設規劃綱要(2024—2035 年)》,教育部等九部門印發《關于加快推進教育數字化的意見》,表明將持續推動“人工智能教育”全方位發展&a…

PDF處理控件Spire.PDF系列教程:如何使用C# 拆分 PDF 文件(完整指南)

PDF文件因其高度的跨平臺兼容性和安全穩定的格式特點,廣泛應用于企業文檔管理和電子資料傳輸中。隨著PDF文檔頁數和內容復雜度的增加,拆分PDF成為優化文檔處理流程、提升辦公效率的重要需求。通過編程方式實現PDF拆分,不僅能自動化處理海量文…

文心4.5開源模型部署實踐

文心4.5開源模型部署實踐 使用fastdeploy本地部署 執行命令: python -m fastdeploy.entrypoints.openai.api_server \--model baidu/ERNIE-4.5-21B-A3B-Paddle \--port 8180 \--metrics-port 8181 \--engine-worker-queue-port 8182 \--max-model-len 32768 \--m…

Python迭代器、生成器、閉包和裝飾器(三器一包)

return、continue、break區別: return只能用在函數里面,表示從函數中返回,函數體內的后續任何代碼都不執行continue只是跳出當前循環,進入下一循環break只是跳出全部循環,如果循環后面還有代碼,會進行執行…

【Java】Maven

一.Maven簡介 Maven的產生主要是為了解決Java項目中的兩個問題: 1.依賴管理: 傳統 Java 項目在引入第三方庫時,需要手動下載 JAR 包并維護復雜的依賴關系。Maven 提供了統一的依賴管理機制,通過簡單的配置即可自動從倉庫下載并引…

人臉活體識別3:C/C++實現人臉眨眼 張嘴 點頭 搖頭識別(可實時檢測)

人臉活體識別3:C/C實現人臉眨眼 張嘴 點頭 搖頭識別(可實時檢測) 目錄 人臉活體識別3:C/C實現人臉眨眼 張嘴 點頭 搖頭識別(可實時檢測) 1. 前言 2.人臉活體識別方法 (1)基于人臉動作的檢測?? (2)?…

【ABAP】 從無到有 新建一個Webdynpro程序

、新建WDA 可從SE80在web dynpro 組件下 創建 并按例以下操作 2、插入窗口 3、相關功能 3-1、展示消息 DATA:lo_api_controller TYPE REF TO if_wd_controller,lo_message_handler TYPE REF TO if_wd_message_manager.lo_api_controller ? wd_this->wd_get_api( ).lo_mess…

ALV常用設置(更新中一)

之前設置了checkbox,但是觸發不了單擊事件,且alv自帶的復選,鼠標移動單擊別處就會自動取消。 **增加多選框到fieldcat,**這一點很重要,然后設置 IF gs_fcat-fieldname sel.gs_fcat-checkbox X. gs_fcat-edit X. …

NumPy 或 PyTorch/TensorFlow 中的張量理解

(2, 2, 3) 形狀的 3D 數組(或張量)的結構。 個人理解: 2個2維數組(張量),2維數組(張量)里面有2個1維向量(張量),1維向量(張量&#x…

Linux環境下使用 C++ 與 OpenCV 實現 ONNX 分類模型推理

實驗環境:Ubuntu 20.0 推理模型:ONNX分類模型 1. 安裝依賴項 首先是需要安裝依賴庫,如g,cmake等,如果已經安裝的話可以忽略 sudo apt install -y g sudo apt install -y cmake sudo apt install -y make sudo apt i…

AJAX 安裝使用教程

一、AJAX 簡介 AJAX(Asynchronous JavaScript and XML)是一種在無需重新加載整個網頁的情況下,能夠與服務器交換數據并更新部分網頁內容的技術。它不是一種新語言,而是使用現有的標準組合:JavaScript XMLHttpRequest…

【牛客算法】牛客網編程題解:小紅拼圖

一、題目介紹 1.1. 題目鏈接 :小紅拼圖 https://www.nowcoder.com/questionTerminal/08b54686f0d14bd784d9d148c68a268a 1.2 題目介紹 小紅正在玩一個拼圖游戲,她有一些完全相同的拼圖組件: 小紅準備用這些組件來拼成一些圖案。這些組件可…

買賣股票的最佳時機--js 算法

一、買賣股票的最佳時機 給定一個數組 prices ,它的第 i 個元素 prices[i] 表示一支給定股票第 i 天的價格。你只能選擇 某一天 買入這只股票,并選擇在 未來的某一個不同的日子 賣出該股票。設計一個算法來計算你所能獲取的最大利潤。返回你可以從這筆交易中獲取的最大利潤。…

C#基礎(WndProc)

WndProc 是操作系統與你的程序“對話”的通道??。當用戶點擊鼠標、按下鍵盤,或系統事件(如窗口移動)發生時,Windows 會將這些事件打包成“消息”,發送給你的窗口,而 WndProc 就是接收和處理這些消息的函數…