
答案1
我歡迎更好的答案,但我的理解是,它是在彙編中手寫的內核啟動代碼(特定於體系結構)(記住,此時我們只有裸機 CPU 和對內存的原始訪問;我們不能訪問存儲在文件系統上的複雜庫,因為我們還沒有文件管理器- 這就像問誰創造了大爆炸)。不要將其與引導程式(將引導磁區從磁碟載入到 RAM 中)混淆。我自己在之前的回答中也對它們感到困惑。
+- - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - + + - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - +
' bootloader ' ' kernel '
' ' ' '
+------+ ' +-----------------------------------+ +------------------------------+ ' ' +-----------------------------+ +---------------------------------------+ '
| BIOS | --> ' | arch/x86/boot/header.S::call main | --> | arch/x86/boot/main.c::main() | ' --> ' | init/main.c::start_kernel() | --> | arch/x86/kernel/setup.c::setup_arch() | '
+------+ ' +-----------------------------------+ +------------------------------+ ' ' +-----------------------------+ +---------------------------------------+ '
' ' ' '
+- - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - + + - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - +
(編輯:這是 Minix,我最初錯誤地將其放入)
+------+ +--------------------+ +------------------+ +------------------------+
| BIOS | --> | Bootloader (mbr.S) | --> | startup (head.S) | --> | kernel/main.c::kmain() |
+------+ +--------------------+ +------------------+ +------------------------+
在 head.S 的末端你會看到這條線
call _C_LABEL(kmain)
這是核心的入口點:
kernel/main.c
我相信head.S
在編譯時附加到內核映像的頂部。 BIOS 知道執行這段程式碼,因為它位於最開始,並且是 RAM 磁碟的根檔案系統。
至於為什麼會有壓縮和未壓縮的部分,我認為是因為核心映像的架構特定的彙編部分,沒有程式設計師足夠熟練地進行壓縮。一旦我們可以跳到kmain
用 C 編寫的例程(但編譯成彙編),我們就可以存取解壓縮例程,這使得核心佔用空間顯著減少。
http://duartes.org/gustavo/blog/post/kernel-boot-process/
使用彙編的入口點
我們喜歡用 C 語言編寫所有內容,但我們無法避免一點彙編。我們將以 x86 組譯語言編寫一個小文件,作為核心的起點。我們的彙編檔案要做的就是呼叫我們用 C 編寫的外部函數,然後停止程式流程。
我們如何確保該彙編程式碼將作為核心的起點?
我們將使用連結器腳本來連結目標檔案以產生最終的核心可執行檔。 (稍後詳細解釋)在此連結描述檔中,我們將明確指定我們希望將二進位檔案載入到位址 0x100000。正如我之前所說,這個位址是核心預期所在的位置。因此,引導程式將負責觸發核心的入口點。
http://arjunsreedharan.org/post/82710718100/kernel-101-lets-write-a-kernel