歡迎來到Linux教程網
Linux教程網
Linux教程網
Linux教程網
您现在的位置: Linux教程網 >> UnixLinux >  >> Linux綜合 >> Linux資訊 >> 更多Linux

Linux的啟動和核心介紹

 作 者: Xiao Man       前幾天大家對Linux的啟動有些討論。   於是整理了一下前段時間與他人交流的提綱,希望起到拋磚引玉的作用。   [email protected]   這是一次對Linux介紹後的整理。   對象是一些剛對Linux核心感興趣,並且准備進一步研究和改造的同志。   因為是由提綱整理而成,有些亂,見諒!       四部分內容:   一、Linux核心源碼結構介紹   二、編譯和配置的過程   三、系統啟動順序的相關文件   四、核心改造的一些經驗   一、   當我們安裝好一個Linux系統,通常核心源碼存放在/usr/src/linux/目錄。   下面先看看這目錄下的各個子目錄及文件。   [/]#cd /usr/src/linux   [linux]#ls -aF   ./ MAINTAINERS drivers/ kernel/ scripts/   ../ Makefile fs/ lib/   COPYING README include/ mm/   CREDITS Rules.make init/ modules/   Documentation/ arch/ ipc/ net/   下面我們逐一描述:   COPYING   GPL版權申明,看後你至少應該知道,你對具有GPL版權的源代碼改動而形成的程序,或使用GPL工具產生的程序,具有使用GPL發表的義務。其中之一就是公開源代碼。   CREDITS   光榮榜,你應當感謝的一些人的信息,其中的每一個人都對Linux做出過很大貢獻。   Documentation/   文檔目錄,可有選擇地看一下你感興趣的部分   MAINTAINERS   維護人員列表,對當前版本的內核各部分都有誰負責,如果你研究的夠深入,可以與他們討論   Makefile   如果你在UNIX編譯過程序,可以看明白README,Linus 所寫,核心及其編譯配置方法簡單介紹Rules.make: make時使用的一些共同規則   arch/   architecture(體系結構)我關心的i386啟動過程在其中,包括Linux在多種平台下的實現。如果要移植系統到一個新的CPU環境中,這就是你要關心的目錄   drivers/   驅動程序目錄,包含大量設備驅動的實現,按類別分子目錄   fs/   文件系統,實現了當前流行的幾乎所有文件系統。Cool   include/   嵌入文件目錄   init/   初始化文件,包含main.c和version.c兩個文件。Initialize   ipc/   ipc的實現,與SYS V兼容   kernel/   最核心代碼,調度,中斷,信號等的處理   lib/   一些工具。   Mm/   內存管理,Memory Manager,虛擬頁、緩沖的實現。   Modules/   模塊文件目錄,用於存放編譯時產生的模塊目標文件(參考編譯過程)   net/   網絡實現,包括TCP/IP在內的大量網絡協議的實現。   Scripts/   描述文件,腳本,用於對核心的配置。       二、   構造內核   常用命令包括:   make config, dep, clean, mrproper, zImage, bzImage, modules, modules_install     (1) make config   核心配置,調用./scripts/Configure 按照arch/i386/config.in 來進行配置。   命令執行完後產生文件.config,其中保存著配置信息。下一次再做make config將產生新的.config文件,原.config被改名為.config.old   (2)make dep   尋找依存關系,產生兩個文件.depend和.hdepend。其中.hdepend表示每個.h文件都包含其它哪些嵌入文件。而.depend 文件有多個,在每個會產生目標文件(.o)文件的目錄下均有,它表示每個目標文件都依賴哪些嵌入文件(.h)。       (3)make clean   清出以前構核所產生的所有目標文件、模塊文件、核心以及一些臨時文件等,不產生任何文件。     (4)make rmproper   刪除所有因構核過程中產生的所有文件,及除了做make clean外,還要刪除.config,.depend等文件,把核心源碼恢復到最原始的狀態。下次構核時就必須重新配置了。       (5)make, make zImage, make bzImage   make:   構核。通過各目錄的Makefile文件進行。會在各個目錄下產生一大堆目標文件,若核心代碼沒有錯誤,將產生文件vmlinux,這就是所構的核心。並產生映射文件System.map通過各目錄的Makefile文件進行。.version 文件中的數加1,表示版本號(又產生一個新的版本了),讓你明白,你已經對核心改動過多少次了。   Make zImage:   在make的基礎上產生壓縮的核心映象文件./arch/$(ARCH)/boot/zImage以及在./arch/$(ARCH)/boot/compresed/目錄下產生一些臨時文件。   Make bzImage:   在make 的基礎上產生壓縮比例更大的核心映象文件./arch/$(ARCH)/boot/bzImage以及在./arch/$(ARCH)/boot/compresed/目錄下產生一些臨時文件。在核心太大時進行。   (6)make modules   編譯模塊文件,你在make config時所配置的所有模塊將在這時編譯,形成模塊目標文件,並把這些目標文件存放在modules目錄中。使用如下命令看一看。   Ls modules   (7)make modules_install   把上面編譯好的模塊目標文件目錄/lib/modules/$KERNEL_VERSION/ 中。比如我的版本是2.0.36,做完這個操作後可使用下面的命令看看:   ls /lib/modules/2.0.36/       相關的命令還有很多,有興趣可看相關資料和Makefile文件。   另外注意,這兒我們產生了一些隱含文件   .config   .oldconfig   .depend   .hdepend   .version   它們的意義應該很清楚了。   三、   系統的啟動順序及相關文件   仍在核心源碼目錄下,看以下幾個文件   ./arch/$ARCH/boot/bootsect.s   ./arch/$ARCH/boot/setup.s   ./init/main.c       bootsect.S 及 setup.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部份比較    把大家所熟知的MS DOS 與linux的開機部份做個粗淺的比較,MS DOS 由位於磁盤上boot sector的boot程序負責把IO.SYS載入內存中,而IO.SYS則負有把DOS的kernel --MSDOS.SYS載入內存的重責大任。而linux則是由位於boot sector 的   bootsect程序負責把setup及linux的kernel載入內存中,再將控制權交給setup。   ##這幾步內容主要參照一個台灣同胞寫的文檔,setup.s的內容希望有人補充。       Start_kernel()   當核心被載入後,首先進入的函數就是start_kernel。   ./init/main.c 中函數start_kernel包含核心的啟動過程及順序。   通過它來看核心整個初始化過程。   首先進行一系列初始化,包括:   trap_init(); ##./arch/i386/kernel/traps.c 陷入   init_IRQ(); ##./arch/i386/kernel/irq.c setup IRQ   sched_init(); ##./kernel/sched.c 調度初始化,並初始化bottom_half   time_init(); ##./arch/i386/kernel/time.c   init_modules(); ##模塊初始化   mem_init(memory_start,memory_end);   buffer_init(); ## ./fs/buffer.c 緩沖區   sock_init(); ## ./net/socket.c socket初始化,並初始化各協議(TCP等)   ipc_init();   sysctl_init();   然後通過調用kernelthread()產生init進程,全權交由init進程處理。調用cpu_idle(NULL)休息。   感興趣又有時間的同志可以寫一個startkernel()函數的詳細分析報告。       下面看一看init進程的工作:   首先創建進程   bdflush ##./fs/buffer.c 緩沖區管理   和kswapd ##./mm/vmscan.c 虛擬內存管理   這兩個進程非常重要   系統初始化(系統調用setup)   系統初始化包含設備初始化及各文件系統初始化。   Sys_setup (./fs/filesystems.c)      -device_setup       -- chr_dev_init(); ##字符設備    blk_dev_init(); ##塊設備    scsi_dev_init(); ##SCSI    net_dev_init(); ##網絡設備    console_map_init(); ##控制台   -binfmt_setup();   -init_nls() ##各文件系統初始化   -init_ext_fs()   -init_ext2_fs()   . .   . .   . .   -init_autofs_fs()   --mount_root() ##mount root fs




 



Copyright © Linux教程網 All Rights Reserved