国产毛片a精品毛-国产毛片黄片-国产毛片久久国产-国产毛片久久精品-青娱乐极品在线-青娱乐精品

Linux內核啟動流程-迅為IMX6ULL開發板(一)

發布時間:2020-7-17 10:30    發布者:就是塔塔
在前面的章節介紹了ubootLinux內核的一些相關內容。在來看Linux內核的大致啟動流程,Linux內核的啟動流程要比uboot復雜的多,涉及到的內容也更多,因此在本章節大致簡單的了解一下Linux內核的啟動流程。有興趣的用戶可以參考其他書籍或資料進行深入了解。
嵌入式linux內核的啟動全過程主要分為三個階段。第一階段為內核自解壓過程,第二階段主要工作是設置ARM處理器工作模式、使能MMU、設置一級頁表等,而第三階段則主要為C代碼,包括內核初始化的全部工作。下面分別進行簡單介紹。
基于迅為-IMX6ULL開發板
30.1 Linux內核啟動(一):Linux內核自解壓過程
Linux內核有兩種映像格式:一種是非壓縮內核,叫Image,另一種是它的壓縮版本,叫zImage。zImage是Image經過壓縮形成的,所以它的大小比Image小。但為了能使用zImage,必須在它的開頭加上解壓縮的代碼,將zImage解壓縮之后才能執行,因此它的執行速度比Image要慢一些
內核壓縮和解壓縮代碼都在目錄kernel/arch/arm/boot/compressed,編譯完成后將產生head.omisc.opiggy.gzip.ovmlinuxdecompress.o這幾個文件,head.o是內核的頭部文件,負責初始設置;misc.o將主要負責內核的解壓工作,它在head.o之后;piggy.gzip.o是一個中間文件,其實是一個壓縮的內核(kernel/vmlinux),只不過沒有和初始化文件及解壓文件鏈接而已;vmlinux是沒有(zImage是壓縮過的內核)壓縮過的內核,就是由piggy.gzip.ohead.omisc.o組成的,而decompress.o是為支持更多的壓縮格式而新引入的。
uboot完成系統引導將Linux內核加載到內存之后,調用do_bootm_linux(),這個函數將跳轉到kernel的起始位置。如果kernel沒有被壓縮,就可以啟動了。如果kernel被壓縮過,則要進行解壓,在壓縮過的kernel頭部有解壓程序。壓縮過的kernel入口第一個文件源碼位置在arch/arm/boot/compressed/head.S。它將調用函數decompress_kernel(),這個函數在文件arch/arm/boot/compressed/misc.c中,decompress_kernel()又調用arch_decomp_setup()進行設置,然后調用gunzip()將內核放于指定的位置。
函數decompress_kernel實現的功能:解壓縮代碼位于kernel/lib/inflate.cinflate.c是從gzip源程序中分離出來的,包含了一些對全局數據的直接引用,在使用時需要直接嵌入到代碼中。gzip壓縮文件時總是在前32K字節的范圍內尋找重復的字符串進行編碼, 在解壓時需要一個至少為32K字節的解壓緩沖區,它定義為window[WSIZE]inflate.c使用get_byte()讀取輸入文件,它被定義成宏來提高效率。輸入緩沖區指針必須定義為inptrinflate.c中對之有減量操作。inflate.c調用flush_window()來輸出window緩沖區中的解壓出的字節串,每次輸出長度用outcnt變量表示。在flush_window()中,還必須對輸出字節串計算CRC并且刷新crc變量。在調用gunzip()開始解壓之前,調用makecrc()初始化CRC計算表。最后gunzip()返回0表示解壓成功。在內核啟動時一般會看到這樣的輸出:
UncompressingLinux...done, booting the kernel.
當然有的內核沒有這樣的輸出,是沒有這一條打印語句。
30.2 Linux內核啟動(二):ARM處理器相關設置
Linux內核自解壓完成后,開始執行內核代碼。內核的入口函數由鏈接腳本vmlinux.lds決定,需要編譯內核源碼,才會生成腳本文件。
首先分析Linux內核的鏈接腳本文件arch/arm/kernel/vmlinux.lds,通過鏈接腳本可以找到Linux內核的第一行程序是從哪里開始執行的。vmlinux.lds文件部分代碼如下:
492 OUTPUT_ARCH(arm)
493 ENTRY(stext)
494 jiffies = jiffies_64;
495 SECTIONS
496 {
497 /*
498 * XXX: The linker does not define how output sections are
499 * assigned to input sections when there are multiple statements
500 * matching the same input section name. There is no documented
501 * order of matching.
502 *
503 * unwind exit sections must be discarded before the rest of the
504 * unwind sections get included.
505 */
506 /DISCARD/ : {
507 *(.ARM.exidx.exit.text)
508 *(.ARM.extab.exit.text)
509
......
645 }
第493行的 ENTRY 指明了Linux內核入口函數為stext,因此要分析Linux內核第二階段的啟動流程,就得先從文件 arch/arm/kernel/head.S 的stext處開始分析。
30.2.1 Linux內核入口函數stext
stextLinux內核的入口地址,在文件arch/arm/kernel/head.S中有如下內容:
/*
* Kernel startup entry point.
* ---------------------------
*
* This is normally called from the decompressor code. The requirements
* are: MMU = off, D-cache = off, I-cache = dont care, r0 = 0,
* r1 = machine nr, r2 = atags or dtb pointer.
.....
*/
以上代碼中的內容顯示。Linux內核啟動之前要求如下:
① 關閉MMU
② 關閉D-cache
③ 不用關心I-cache
④ r0 = 0
⑤ r1 = machine nr(機器ID號)
⑥ r2 = atags或者設備樹(dts)首地址
Linux內核的入口點stext其實相當于內核的入口函數,stext函數代碼如下:
80 ENTRY(stext)
......
91 @ ensure svc mode and all interrupts masked
92 safe_svcmode_maskall r9
93
94 mrc p15, 0, r9, c0, c0 @ get processor id
95 bl __lookup_processor_type @ r5=procinfo r9=cpuid
96 movs r10, r5 @ invalid processor (r5=0)?
97 THUMB( it eq ) @ force fixup-able long branch encoding
98 beq __error_p @ yes, error 'p'
99
......
107
108 #ifndef CONFIG_XIP_KERNEL
......
113 #else
114 ldr r8, =PLAT_PHYS_OFFSET @ always constant in this case
115 #endif
116
117 /*
118 * r1 = machine no, r2 = atags or dtb,
119 * r8 = phys_offset, r9 = cpuid, r10 = procinfo
120 */
121 bl __vet_atags
......
128 bl __create_page_tables
129
130 /*
131 * The following calls CPU specific code in a position independent
132 * manner. See arch/arm/mm/proc-*.S for details. r10 = base of
133 * xxx_proc_info structure selected by __lookup_processor_type
134 * above. On return, the CPU will be ready for the MMU to be
135 * turned on, and r0 will hold the CPU control register value.
136 */
137 ldr r13, =__mmap_switched @ address to jump to after
138 @ mmu has been enabled
139 adr lr, BSYM(1f) @ return (PIC) address
140 mov r8, r4 @ set TTBR1 to swapper_pg_dir
141 ldr r12, [r10, #PROCINFO_INITFUNC]
142 add r12, r12, r10
143 ret r12
144 1: b __enable_mmu
145 ENDPROC(stext)
第92行,調用函數safe_svcmode_maskall確保CPU處于SVC模式,并且關閉了所有的中斷。safe_svcmode_maskall定義在文件arch/arm/include/asm/assembler.h 中。
第94行,讀處理器ID,ID值保存在r9寄存器中。
第95行,__lookup_processor_type調用結束返回原程序時,會將返回結果保存到寄存器中。其中r5寄存器返回一個用來描述處理器的結構體地址,并對r5進行判斷,如果r5的值為0則說明不支持這種處理器,將進入__error_p procinfo proc_info_list Linux內核將每種處理器都抽象為一個 proc_info_list 結構體,每種處理器都對應一個procinfo。proc_info_list在文件arch/arm/include/asm/procinfo.h 中的定義如下:
struct proc_info_list {
unsigned int cpu_val;
unsigned int cpu_mask;
unsigned long __cpu_mm_mmu_flags; /* used by head.S */
unsigned long   __cpu_io_mmu_flags; /* used by head.S */
unsigned long __cpu_flush; /* used by head.S */
const char *arch_name;
const char *elf_name;
unsigned int elf_hwcap;
const char *cpu_name;
struct processor *proc;
struct cpu_tlb_fns *tlb;
struct cpu_user_fns *user;
struct cpu_cache_fns *cache;
};
121 行,調用函數__vet_atags 驗證 atags 或設備樹(dtb)的合法性。函數__vet_atags 定義在文件 arch/arm/kernel/head-common.S 中。
128 行,調用函數__create_page_tables 創建頁表。
137 行,將函數__mmap_switched 的地址保存到 r13 寄存器中。__mmap_switched 定義在文件 arch/arm/kernel/head-common.S,__mmap_switched 最終會調用 start_kernel 函數。
144 ,調用 __enable_mmu 使 MMU __enable_mmu arch/arm/kernel/head.S 中。__enable_mmu 最終會通過調用__turn_mmu_on 來打開 MMU,__turn_mmu_on 最后會執行 r13 里面保存的__mmap_switched 函數。
30.2.2 _mmap_switched 函數
__mmap_switched 函數定義在文件arch/arm/kernel/head-common.S中,函數代碼如下:
81 __mmap_switched:
82 adr r3, __mmap_switched_data
83
84 ldmia r3!, {r4, r5, r6, r7}
85 cmp r4, r5 @ Copy data segment if needed
86 1: cmpne r5, r6
87 ldrne fp, [r4], #4
88 strne fp, [r5], #4
89 bne 1b
90
91 mov fp, #0 @ Clear BSS (and zero fp)
92 1: cmp r6, r7
93 strcc fp, [r6],#4
94 bcc 1b
95
96 ARM( ldmia r3, {r4, r5, r6, r7, sp})
97 THUMB( ldmia r3, {r4, r5, r6, r7} )
98 THUMB( ldr sp, [r3, #16] )
99 str r9, [r4] @ Save processor ID
100 str r1, [r5] @ Save machine type
101 str r2, [r6] @ Save atags pointer
102 cmp r7, #0
103 strne r0, [r7] @ Save control register values
104 b start_kernel
105 ENDPROC(__mmap_switched)
104 行最終調用 start_kernel 來啟動 Linux 內核,start_kernel 函數定義在文件 init/main.c中。
從start_kernel 函數開始Linux內核啟動進入到下一個階段。
下面內容請關注:Linux內核啟動流程-迅為IMX6ULL開發板(二)

本文地址:http://m.qingdxww.cn/thread-596614-1-1.html     【打印本頁】

本站部分文章為轉載或網友發布,目的在于傳遞和分享信息,并不代表本網贊同其觀點和對其真實性負責;文章版權歸原作者及原出處所有,如涉及作品內容、版權和其它問題,我們將根據著作權人的要求,第一時間更正或刪除。
您需要登錄后才可以發表評論 登錄 | 立即注冊

廠商推薦

  • Microchip視頻專區
  • 利用SAM E54 Xplained Pro評估工具包演示CAN轉USB橋接器以及基于CAN的主機和自舉程序應用程序
  • 使用SAM-IoT Wx v2開發板演示AWS IoT Core應用程序
  • 使用Harmony3加速TCP/IP應用的開發培訓教程
  • 集成高級模擬外設的PIC18F-Q71家族介紹培訓教程
  • 貿澤電子(Mouser)專區
關于我們  -  服務條款  -  使用指南  -  站點地圖  -  友情鏈接  -  聯系我們
電子工程網 © 版權所有   京ICP備16069177號 | 京公網安備11010502021702
快速回復 返回頂部 返回列表
主站蜘蛛池模板: 婷婷尹人香蕉久久天堂 | 免费高清毛片 | 欧美成在线视频 | 欧美日韩在线视频播放 | 青青草成人免费在线视频 | 最新色导航| 欧美高清一区二区三区欧美 | 亚洲精品一 | 最新国产三级久久 | 高清精品一区二区三区一区 | 四虎欧美在线观看免费 | 日本一本免费一二区 | 六月婷婷色| 中文字幕在线看视频一区二区三区 | 一级片网址 | 久久影院午夜伦手机不四虎卡 | 91国偷自产一区二区三区蜜臀 | 四虎欧美在线观看免费 | 毛片视频大全 | 天天干天天操天天透 | 日本精品一区二区三区在线观看 | 99热这里只有精品国产免费 | 男人j桶进女人p无遮挡 | 毛片大片免费看 | 免费国产黄 | 一区二区三区四区在线免费观看 | sihu在线观看| 日本不卡在线视频高清免费 | 国产精品视频1区 | 总裁虐我千百遍电视剧免费播放 | 国产一区二区三区手机在线观看 | 毛片在线视频观看 | 四虎成人免费网站在线 | 激情啪啪精品一区二区 | 69免费视频大片 | 欧美日韩国产在线人成app | 伊人手机视频 | 99re在线视频观看 | 婷婷综合在线观看丁香 | 国产精品大全国产精品 | 日本高清不卡网站免费 |