當前位置:編程學習大全網 - 源碼下載 - linux的內核運行原理是怎麽樣的呢?如何從開機,到加載內核鏡像到內存?

linux的內核運行原理是怎麽樣的呢?如何從開機,到加載內核鏡像到內存?

當PC啟動時,Intel系列的CPU首先進入的是實模式,並開始執行位於地址0xFFFF0處

的代碼,也就是ROM-BIOS起始位置的代碼。BIOS先進行壹系列的系統自檢,然後初始化位

於地址0的中斷向量表。最後BIOS將啟動盤的第壹個扇區裝入到0x7C00,並開始執行此處

的代碼。這就是對內核初始化過程的壹個最簡單的描述。

最初,linux核心的最開始部分是用8086匯編語言編寫的。當開始運行時,核心將自

己裝入到絕對地址0x90000,再將其後的2k字節裝入到地址0x90200處,最後將核心的其余

部分裝入到0x10000。

當系統裝入時,會顯示Loading...信息。裝入完成後,控制轉向另壹個實模式下的匯

編語言代碼boot/Setup.S。Setup部分首先設置壹些系統的硬件設備,然後將核心從

0x10000處移至0x1000處。這時系統轉入保護模式,開始執行位於0x1000處的代碼。

接下來是內核的解壓縮。0x1000處的代碼來自於文件Boot/head.S,它用來初始化寄

存器和調用decompress_kernel( )程序。decompress_kernel( )程序由Boot/inflate.c,

Boot/unzip.c和Boot../misc.c組成。解壓縮後的數據被裝入到了0x100000處,這也是

linux不能在內存小於2M的環境下運行的主要原因。

解壓後的代碼在0x1010000處開始執行,緊接著所有的32位的設置都將完成: IDT、

GDT和LDT將被裝入,處理器初始化完畢,設置好內存頁面,最終調用start_kernel過程。

這大概是整個內核中最為復雜的部分。

[系統開始運行]

linux kernel 最早的C代碼從匯編標記startup_32開始執行

startup_32:

start_kernel

lock_kernel

trap_init

init_IRQ

sched_init

softirq_init

time_init

console_init

#ifdef CONFIG_MODULES

init_modules

#endif

kmem_cache_init

sti

calibrate_delay

mem_init

kmem_cache_sizes_init

pgtable_cache_init

fork_init

proc_caches_init

vfs_caches_init

buffer_init

page_cache_init

signals_init

#ifdef CONFIG_PROC_FS

proc_root_init

#endif

#if defined(CONFIG_SYSVIPC)

ipc_init

#endif

check_bugs

smp_init

rest_init

kernel_thread

unlock_kernel

cpu_idle

startup_32 [arch/i386/kernel/head.S]

start_kernel [init/main.c]

lock_kernel [include/asm/smplock.h]

trap_init [arch/i386/kernel/traps.c]

init_IRQ [arch/i386/kernel/i8259.c]

sched_init [kernel/sched.c]

softirq_init [kernel/softirq.c]

time_init [arch/i386/kernel/time.c]

console_init [drivers/char/tty_io.c]

init_modules [kernel/module.c]

kmem_cache_init [mm/slab.c]

sti [include/asm/system.h]

calibrate_delay [init/main.c]

mem_init [arch/i386/mm/init.c]

kmem_cache_sizes_init [mm/slab.c]

pgtable_cache_init [arch/i386/mm/init.c]

fork_init [kernel/fork.c]

proc_caches_init

vfs_caches_init [fs/dcache.c]

buffer_init [fs/buffer.c]

page_cache_init [mm/filemap.c]

signals_init [kernel/signal.c]

proc_root_init [fs/proc/root.c]

ipc_init [ipc/util.c]

check_bugs [include/asm/bugs.h]

smp_init [init/main.c]

rest_init

kernel_thread [arch/i386/kernel/process.c]

unlock_kernel [include/asm/smplock.h]

cpu_idle [arch/i386/kernel/process.c]

start_kernel( )程序用於初始化系統內核的各個部分,包括:

*設置內存邊界,調用paging_init( )初始化內存頁面。

*初始化陷阱,中斷通道和調度。

*對命令行進行語法分析。

*初始化設備驅動程序和磁盤緩沖區。

*校對延遲循環。

最後的function'rest_init' 作了以下工作:

開辟內核線程'init'

調用unlock_kernel

建立內核運行的cpu_idle環, 如果沒有調度,就壹直死循環

實際上start_kernel永遠不能終止.它會無窮地循環執行cpu_idle.

最後,系統核心轉向move_to_user_mode( ),以便創建初始化進程(init)。此後,進程0開始進入無限循環。

初始化進程開始執行/etc/init、/bin/init 或/sbin /init中的壹個之後,系統內核就不再對程序進行直接控制了。之後系統內核的作用主要是給進程提供系統調用,以及提供異步中斷事件的處理。多任務機制已經建立起來,並開始處理多個用戶的登錄和fork( )創建的進程。

[init]

init是第壹個進程,或者說內核線程

init

lock_kernel

do_basic_setup

mtrr_init

sysctl_init

pci_init

sock_init

start_context_thread

do_init_calls

(*call())-> kswapd_init

prepare_namespace

free_initmem

unlock_kernel

execve

[目錄]

--------------------------------------------------------------------------------

啟動步驟

系統引導:

涉及的文件

./arch/$ARCH/boot/bootsect.s

./arch/$ARCH/boot/setup.s

bootsect.S

這個程序是linux kernel的第壹個程序,包括了linux自己的bootstrap程序,

但是在說明這個程序前,必須先說明壹般IBM PC開機時的動作(此處的開機是指

"打開PC的電源"):

壹般PC在電源壹開時,是由內存中地址FFFF:0000開始執行(這個地址壹定

在ROM BIOS中,ROM BIOS壹般是在FEOOOh到FFFFFh中),而此處的內容則是壹個

jump指令,jump到另壹個位於ROM BIOS中的位置,開始執行壹系列的動作,包

括了檢查RAM,keyboard,顯示器,軟硬磁盤等等,這些動作是由系統測試代碼

(system test code)來執行的,隨著制作BIOS廠商的不同而會有些許差異,但都

是大同小異,讀者可自行觀察自家機器開機時,螢幕上所顯示的檢查訊息。

緊接著系統測試碼之後,控制權會轉移給ROM中的啟動程序

(ROM bootstrap routine),這個程序會將磁盤上的第零軌第零扇區讀入

內存中(這就是壹般所謂的boot sector,如果妳曾接觸過電腦病

毒,就大概聽過它的大名),至於被讀到內存的哪裏呢? --絕對

位置07C0:0000(即07C00h處),這是IBM系列PC的特性。而位在linux開機

磁盤的boot sector上的正是linux的bootsect程序,也就是說,bootsect是

第壹個被讀入內存中並執行的程序。現在,我們可以開始來

看看到底bootsect做了什麽。

第壹步

首先,bootsect將它"自己"從被ROM BIOS載入的絕對地址0x7C00處搬到

0x90000處,然後利用壹個jmpi(jump indirectly)的指令,跳到新位置的

jmpi的下壹行去執行,

第二步

接著,將其他segment registers包括DS,ES,SS都指向0x9000這個位置,

與CS看齊。另外將SP及DX指向壹任意位移地址( offset ),這個地址等壹下

會用來存放磁盤參數表(disk para- meter table )

第三步

接著利用BIOS中斷服務int 13h的第0號功能,重置磁盤控制器,使得剛才

的設定發揮功能。

第四步

完成重置磁盤控制器之後,bootsect就從磁盤上讀入緊鄰著bootsect的setup

程序,也就是setup.S,此讀入動作是利用BIOS中斷服務int 13h的第2號功能。

setup的image將會讀入至程序所指定的內存絕對地址0x90200處,也就是在內存

中緊鄰著bootsect 所在的位置。待setup的image讀入內存後,利用BIOS中斷服

務int 13h的第8號功能讀取目前磁盤的參數。

第五步

再來,就要讀入真正linux的kernel了,也就是妳可以在linux的根目錄下看

到的"vmlinuz" 。在讀入前,將會先呼叫BIOS中斷服務int 10h 的第3號功能,

讀取遊標位置,之後再呼叫BIOS 中斷服務int 10h的第13h號功能,在螢幕上輸

出字串"Loading",這個字串在boot linux時都會首先被看到,相信大家應該覺

得很眼熟吧。

第六步

接下來做的事是檢查root device,之後就仿照壹開始的方法,利用indirect

jump 跳至剛剛已讀入的setup部份

第七步

setup.S完成在實模式下版本檢查,並將硬盤,鼠標,內存參數寫入到 INITSEG

中,並負責進入保護模式。

第八步

操作系統的初始化。

  • 上一篇:python的叠代器為什麽壹定要實現
  • 下一篇:古龍種的包含物種
  • copyright 2024編程學習大全網