II、實模式下的初始化
實模式下的初始化,主要是指從內核引導成功後,到進入保護模式之前系統所做的一些處理。在內核源碼中對應的程序是 /Arch/i386/boot/setup.S;以下部分主要是針對此文件進行的分析。這部分的分析主要是要弄懂它的處理流程和INITSEG(9000:0000)段參數表的建立,此參數表包含了很多硬件參數,這些都是以後進行保護模式下初始化,以及核心建立的基礎。
1. 幾個其它相關文件:
<1> /Arch/i386/boot/bootsect.S
<2> /include/linux/config.h
<3> /include/asm/boot.h
<4> /include/ asm/segment.h
<5> /include/linux/version.h
<6> /include/linux/compile.h
2. 實模式下的初始化過程分析:
INITSEG(9000:0000)段參數表:(參見Include/linux/tty.h)
參數名
偏移量(段址均為0x9000) 長度Byte參考文件
PARAM_CURSOR_POS 0x0000 2 Arch/i386/boot/video.S extended mem Size 0x0002 2 Arch/i386/boot/setup.SPARAM_VIDEO_PAGE
0x0004 2 Arch/i386/boot/video.S PARAM_VIDEO_MODE 0x0006 1 Arch/i386/boot/video.S PARAM_VIDEO_COLS 0x0007 1 Arch/i386/boot/video.S 沒用 0x0008 2 Include/linux/tty.h PARAM_VIDEO_EGA_BX 0x000a 2 Arch/i386/boot/video.S 沒用 0x000c 2 Include/linux/tty.h PARAM_VIDEO_LINES 0x000e 1 Arch/i386/boot/video.S PARAM_HAVE_VGA 0x000f 1 Arch/i386/boot/video.S PARAM_FONT_POINTS 0x0010 2 Arch/i386/boot/video.S PARAM_LFB_WIDTH 0x0012 2 Arch/i386/boot/video.S PARAM_LFB_HEIGHT 0x0014 2 Arch/i386/boot/video.S PARAM_LFB_DEPTH 0x0016 2 Arch/i386/boot/video.S PARAM_LFB_BASE 0x0018 4 Arch/i386/boot/video.S PARAM_LFB_SIZE 0x001c 4 Arch/i386/boot/video.S 暫未用① 0x0020 4 Include/linux/tty.h PARAM_LFB_LINELENGTH 0x0024 2 Arch/i386/boot/video.S PARAM_LFB_COLORS 0x0026 6 Arch/i386/boot/video.S 暫未用② 0x002c 2 Arch/i386/boot/video.S PARAM_VESAPM_SEG 0x002e 2 Arch/i386/boot/video.S PARAM_VESAPM_OFF 0x0030 2 Arch/i386/boot/video.S PARAM_LFB_PAGES 0x0032 2 Arch/i386/boot/video.S 保留 0x0034--0x003f Include/linux/tty.h APM BIOS Version③ 0x0040 2 Arch/i386/boot/setup.S BIOS code segment 0x0042 2 Arch/i386/boot/setup.S BIOS entry offset 0x0044 4 Arch/i386/boot/setup.S BIOS 16 bit code seg 0x0048 2 Arch/i386/boot/setup.S BIOS data segment 0x004a 2 Arch/i386/boot/setup.S 支持32位標志④ 0x004c 2 Arch/i386/boot/setup.S BIOS code seg length 0x004e 4 Arch/i386/boot/setup.S BIOS data seg length 0x0052 2 Arch/i386/boot/setup.S hd0 參數 0x0080 16 Arch/i386/boot/setup.S hd0 參數 0x0090 16 Arch/i386/boot/setup.S PS/2 device 標志⑤ 0x01ff 1 Arch/i386/boot/setup.S* 注: ① Include/linux/tty.h : CL_MAGIC and CL_OFFSET here
Include/linux/tty.h :
unsigned char rsvd_size; /* 0x2c */
unsigned char rsvd_pos; /* 0x2d */
③ 0表示沒有APM BIOS
④ 0x0002置位表示支持32位模式
⑤ 0表示沒有,0x0aa表示有鼠標器
III、保護模式下的初始化
保護模式下的初始化,是指處理機進入保護模式後到運行系統第一個內核程序過程中系統所做的一些處理。保護模式下的初始化在內核源碼中對應的程序是 /Arch/i386/boot/compressed/head.S 和 /Arch/i386/KERNEL/head.S ;以下部分主要是針對這兩個文件進行的分析。
幾個相關文件:
<1.> /Arch/i386/boot/compressed/head.S
<2.> /Arch/i386/KERNEL/head.S
<3.> //Arch/i386/boot/compressed/MISC.c
<4.> /Arch/i386/boot/setup.S
<5.> /include/ asm/segment.h
<6.> /arch/i386/kernel/traps.c
<7.> /include/i386/desc.h
<8.> /include/asm-i386/processor.h
保護模式下的初始化過程分析:
一、/Arch/i386/KERNEL/head.S流程:
二、/Arch/i386/boot/compressed/head.S流程:
從流程圖中可以看到,保護模式下的初始化主要干了這樣幾件事:
解壓內核到0x100000處、
建立頁目錄和pg0頁表並啟動分頁功能(即虛存管理功能)、
保存實模式下測到的硬件信息到empty_zero_page、初始化命令緩存區、
檢測cpu類型、檢查協處理器、
重新建立gdt全局描述符表、和中斷描述附表idt;
從頁目錄和pg0頁表可以看出,0�;4M物理內存被用作系統區,它被映射到系統段線性空間的0�;4M和3G�;3G+4M;即系統可以通過訪問這兩個段來訪問實際的0�;4M物理內存,也就是系統所在的區域;
本來在實模式下初始化時已經建立了全局描述符表gdt,而此處重新建立全局描述符表gdt則主要是出於兩個原因:一個就是若內核是大內核bzimag,則以前建立的gdt,可能已經在解壓時被覆蓋掉了所以,在這個源碼文件中均只采用相對轉移指令jxx nf或jxx nb;二是以前建立的gdt是建立在實地址方式下的,而現在則是在啟用保護虛擬地址方式之後建立的,也即現在的gdt是建立在邏輯地址(即線性地址)上的;
每次建立新的gdt後和啟用保護虛擬地址方式後都必須重新裝載系統棧和重新初始化各段寄存器:cs,ds,es,fs,gs;
從實模式下的初始化和保護模式下的初始化過程可以看出,linux系統由實模式進入到保護模式的過程大致如下:
6.由於分頁機制只能在保護模式下啟動,不能在實模式下啟動,所以第一步是必要的;又因為在386保護模式下gdt和idt是建立在邏輯地址(線性地址)上的,所以第三步也是必要的;
7.經過實模式和保護模式下的初始後,主要系統數據分布如下:
位置 系統數據 大小 0x101000 頁目錄swapper_pg_dir 4K 0x102000 頁表pg0 4K 0x103000 empty_bad_page 4K 0x104000 empty_bad_page_table 4K 0x105000 empty_zero_page 4K 0x105000 系統硬件參數 2K 0x105800 命令緩沖區 2K 0x106000 全局描述附表gdt_table 4192B
從上面對Linux系統的初始化過程的分析可以看出,以程序執行流程為線索、一線串珠,就是按照程序的執行先後順序,弄懂程序執行的各個階段所進行的處理,及其各階段之間的相互聯系。而流程圖應該是這種分析方法最合適的表達工具。
事實上,以程序執行流程為線索,是分析任何源代碼都首選的方法。由於操作系統的特殊性,光用這種方法是遠遠不夠的。當然用這種方法來分析系統的初始化過程或用戶進程的執行流程應該說是很有效的。