墨跡這麼久,總算開始核心源**分析了。
階段1大部分為彙編, 以程式啟動到執行到start_kernel函式為第一階段。 大概流程如下:
變數與檔案的對應關係。
thumb: src\arch\arm\include\asm\unified.h
head.s的很多定義在src\arch\arm\kernel\head-common.s
struct proc_info_list :src\arch\arm\include\asm\procinfo.h
proc_info_sz : build\include\generated\asm-offsets.h:
proc.info.init : src\arch\arm\mm\proc-arm920.s
page_offset:src\arch\arm\include\asm\memory.h = config_page_offset = 0xc0000000
首先從從程式入口處開始分析,linux核心下檔案多不勝數,那麼從**開始找到程式入口位址呢?
源**寫好後,肯定是先使用編譯工具編譯**,而編譯工具也有相關的檔案的,從這個思路,找到
vmlinux.lds
(src\arch\arm\kernel\vmlinux.lds
),該檔案指導
arm-linux-ld
如何工作。該檔案開始有
output_arch(arm)
entry(stext)
jiffies = jiffies_64;
sections
是將0x8c, 0x90, 0x94
位址裡的內容載入到
r4,r5, r6
去,因此等效於將
0xc000808c, 0x c0008090, 0xc0008094
位址裡的內容載入到
r4,r5, r6
去, 0xc000808c
位址的記憶體裡面的內容就是他的位址,為
0xc000808c。
因此上面
r3= 0x8c
為實際的實體地址,而
0x8c
對應的虛擬位址為
0xc000808c。
根據pa1 – va1 = pa2 – va2 = 0x8c - 0xc000808c,
即pa – va
值確定了,編譯後
va的值也確定了,所以可以反推所有的執行時刻**所在的實體地址。
asm-offsets.c (src\arch\arm\kernel):130 中有:
define(procinfo_initfunc, offsetof(struct proc_info_list, __cpu_flush));
src/arch/arm/include/asm/procinfo.h
中有__cpu_flush
定義:
structproc_info_list;
src/arch/arm/mm/pro-arm920.s
中定義了
structproc_info_list __arm920_proc_info
,其段在
.proc.info.init :
.section ".proc.info.init",#alloc,#execinstr
.type __arm920_proc_info,#object
__arm920_proc_info:
.long0x41009200
.long0xff00fff0
.longpmd_type_sect|\
pmd_sect_bufferable|\
pmd_sect_cacheable|\
pmd_bit4|\
pmd_sect_ap_write|\
pmd_sect_ap_read
.longpmd_type_sect|\
pmd_bit4|\
pmd_sect_ap_write|\
pmd_sect_ap_read
b __arm920_setup@ __cpu_flush
.longcpu_arch_name
.longcpu_elf_name
.longhwcap_swp|hwcap_half|hwcap_thumb
.longcpu_arm920_name
.longarm920_processor_functions
.longv4wbi_tlb_fns
.longv4wb_user_fns
在src\arch\arm\kernel\vmlinux.lds中有:
.init.proc.info :
.type__arm920_setup,#function
__arm920_setup:
movr0,#0
mcr p15,0,r0,c7,c7 @ invalidate i,d caches on v4
mcr p15,0,r0,c7,c10,4@ drain write buffer on v4
#ifdefconfig_mmu
mcr p15,0,r0,c8,c7 @ invalidate i,d tlbs on v4
#endif
adr r5,arm920_crval
ldmia r5,
mrc p15,0,r0,c1,c0 @ get control register v4
bic r0,r0,r5
orr r0,r0,r6
movpc,lr
.size __arm920_setup,.-__arm920_setup
綜上: arm(add pc, r10,#procinfo_initfunc):是 執行函式 __arm920_setup, 該函式是對mmu作一些初始化。
此處省略,在文章【linux】mm記憶體管理
有關於mmu比較詳細的分析。
進入階段2:
src\init\main.c: asmlinkage void __init start_kernel(void)
start_kernel: 第二階段啟動入口,開始熟悉的c語言之旅。
src\include\linux\init.h: __init
第二階段內容太多,不在這裡具體寫,後面結合具體例子再說,比如說明sysfs檔案系統時,會有
/sys目錄建立: start_kernel→rest_init→kernel_init→kernel_init_freeable→do_basic_setup→ driver_init的流程說明。
從start_kernel到 shell的流程:start_kernel→rest_init→kernel_init→run_init_process
啟動linux Linux系統啟動流程
linux系統啟動流程 電源開關 手動操作按鈕 加電自啟動 載入bios 最接近硬體的軟體 各家廠商都會開發適合自己主機板的bios bios加電自檢 只有硬體沒有問題的情況下才能執行軟體 機器自檢後 引導系統。bios設定好的 預設讀取主引導記錄 mbr 即磁碟的地0個煮面的第0個磁軌的第乙個扇區...
Linux Linux是怎麼啟動的
昨天筆試考了一道關於linux系統啟動的過程,當時沒答上來,現在整理出來 其實並不複雜 按下電源按鈕的直到歡迎頁出來之後,linux總共做的事可以分為五步來完成。1 bios加電自檢 加電自檢,檢測硬體裝置。然後按照cmos上面的順序來搜尋處在活動狀態下的可以引導的裝置。可以是光碟機 軟盤 usb等...
uboot啟動流程概述 uboot啟動流程
u boot系統啟動流程 大多數bootloader都分為stage1和stage2兩大部分,u boot也不例外。依賴於cpu體系結構的 如裝置初始化 等 通常都放在stage1,且可以用組合語言來實現,而stage2則通常用c語言來實現,這樣可以實現複雜的功能,而且有更好的可讀性和移植性。2.1...