關注v-x-公-眾-號:【嵌入式基地】
后-臺-回-復:【電賽】 即可獲資料
回復【編程】即可獲取
包括有:C、C++、C#、JAVA、Python、JavaScript、PHP、資料庫、微信小程式、人工智能、嵌入式、Linux、Unix、QT、物聯網、演算法導論、大資料等資料

Linux內核加載程序
通常,Linux內核都是經過gzip加載過之后的映像檔案,
- bootloader復制壓縮內核到記憶體空間,
- 內核自解壓,
- 運行內核,
編譯完成的Linux內核存放在哪里?
- ./vmlinux elf格式未壓縮內核,
- arch/arm/boot/compressed/vmlinux 壓縮以后的elf格式內核,
- arch/arm/boot/zImage 壓縮內核,
壓縮內核(zImage)的入口
-
/arch/arm/boot/compressed/vmlinux.lds 該檔案為編譯器指定link順序,
-
ENTRY(_start) 壓縮內核從.start段開始執行,
-
在/arch/arm/boot/compressed/head.S中執行以下愛操作:
(1)檢測系統空間, (2)初始化C代碼空間, (3)跳轉到C代碼decompress_kernel, arch/arm/boot/compressed/misc.c中,
解壓之前的串口輸出
- include/asm-arm/arch-s3c2410/uncompress.h 中定義了puts作為串口輸出函式,
- 解壓結束之后,程式跳轉到r5:解壓之后內核的起始地址,
開始真正的Linux內核
1、入口在arch/arm/kernel/head-armv.S
2、查找處理器型別
__lookup_processor_type
__lookup_architecture_type
3、初始化頁表:__creat_page_tables
4、初始化C代碼空間
5、跳轉到C代碼中,start_kernel
ARM的MMU單元
MMU:記憶體管理單元
作用:
- 虛擬地址到物理地址的映射
- 存盤器訪問權限
- 控制Cache
通過MMU的訪存
- MMU會先查找TLB中的虛擬地址表
- 如果TLB中沒有虛擬地址的入口,硬體從主存盤器中的轉換表中獲取轉換與訪問權限,
ARM的MMU訪存原理

ARM的MMU頁表格式
MMU支持基于節或者頁的存盤器訪問,
- 節:1MB的存盤器塊
- 大頁:64KB的存盤器塊
- 小頁:4KB的存盤器塊
- 微頁:1KB的存盤器塊
頁表的級別
存在主存盤器內的轉換頁表有兩個級別:
- 第一級表:存盤節轉換表與指向第二級表的指標
- 第二級表:
(1)存盤大頁和小頁的轉換表,
(2)存盤微頁的轉換表,
一級頁表的地址
第一級表占用空間16KB,必須16KB對齊

第一級描述符
一級表每個入口描述了它所關聯的1MB虛擬地址是如何映射的,

節描述符
- Bits[1:0] 描述符型別(10b 表示節描述符)
- Bits[3:2] 高速快取(cache)和緩沖位(buffer)
- Bits[4] 由具體實作定義
- Bits[8:5] 控制的節的16 種域之一
- Bits[9] 現在沒有使用,應該為零
- Bits[11:10] 訪問控制(AP)
- Bits[19:12] 現在沒有使用,應該為零
- Bits[31:20] 節基址,形成物理地址的高12 位
節的轉換程序

臨時內核頁表的創建 __create_page_tables
__create_page_tables:
pgtbl r4 @ page table address 0x30008000-0x4000
mov r0, r4 @r0=0x30004000
mov r3, #0
add r2, r0, #0x4000
1: str r3, [r0], #4
str r3, [r0], #4
str r3, [r0], #4
str r3, [r0], #4
teq r0, r2
bne 1b
把一級頁表0x30004000-0xa0080000清空
krnladr r2, r4 @ start of kernel
r4=0xa0004000,r2 = 內核起始地址所在1MB對齊空間,0x30000000
add r3, r8, r2 @ flags + kernel base
r8 為從處理器資訊中得到的MMU 頁表標志,r8=0xc0e, r3=0x30000c0e
str r3, [r4, r2, lsr #18]@ identity mapping
地址:0x300068000, value:0x30000c0e
add r0, r4, #(TEXTADDR & 0xff000000) >> 18
@ start of kernel
bic r2, r3, #0x00f00000
str r2, [r0] @ PAGE_OFFSET + 0MB
add r0, r0, #(TEXTADDR & 0x00f00000) >> 18
str r3, [r0], #4 @ KERNEL + 0MB
映射表內容

映射結果

進入C代碼
init/main.c中的start_kernel函式,進入到了Linux內核代碼中,
- printk函式
- 重新初始化頁表
- 初始化中斷,trap_init
- 設定系統定時器、控制臺…
- 創建內核行程init
轉載請註明出處,本文鏈接:https://www.uj5u.com/qita/280278.html
標籤:其他
上一篇:淺聊Linux的五種IO模型
下一篇:溫度傳感器、VB.NET
