解壓縮Linux內核的工作由另外一個startup_32( )函數來完成。該函數位于/usr/src/linux-2.4.2/arch/i386/kernel/head.S文件中。
這時你可能會說兩個不同的函數用同一個名字不會出錯嗎?答案是不會的。因為兩個函數都是到自己初始地址去執行,并且都有自己的執行環境,所以不會出錯。
下面我們來看一下第二個startup_32( )函數的功能。當執行這個函數時,實際上是為第一個Linux進程(process 0)設置環境。這個函數將執行下面的操作:
(1)段寄存器將以最后的值進行初始化;
(2)為process 0設置內核模式棧;
(3)調用并且執行setup_idt( )函數,該函數將把所有的IDT填充空值;
(4)把從BIOS中獲得的參數放在第一頁的框架中;
(5)識別處理器的模式;
(6)使用GDT和IDT表加載gdtr和idtr寄存器;
(7)最后跳到start_kernel( )函數。
start_kernel( )函數功能
start_kernel( )函數完成Linux內核的初始化工作。這個函數執行后,所有的基本內核組件都將被初始化。這也是整個啟動過程的最后一步。
該函數將完成以下的功能:
(1)執行paging_init( )函數初始化頁表(Page Tables);
(2)執行mem_init( )函數初始化頁描述符(Page Descriptors);
(3)執行trap_init( ) 和 init_IRQ( )函數,最后一次對IDT進行初始化;
(4)執行kmem_cache_init( )和kmem_cache_sizes_init ( )函數,對Slab Allocator進行初始化;
(5)執行time_init( )函數,初始化系統日期和時間;
(6)內核的線程process 1是通過調用kernel_thread( )來完成的。接著就建立其它的內核線程并且執行/sbin/init程序。
到此屏幕上就會顯示“Linux version 2.4.2 ……”信息。此外,還會顯示很多其它信息。最后,就會出現用戶的登錄提示符。這是在告訴用戶Linux內核已經加載完成,用戶已經可以使用。
總結
到現在為止,整個啟動過程都已經描述完畢。其中提到的許多詞匯我都沒有解釋,只簡要說了一下IDT、GDT、eip寄存器和cs寄存器等。