国产探花免费观看_亚洲丰满少妇自慰呻吟_97日韩有码在线_资源在线日韩欧美_一区二区精品毛片,辰东完美世界有声小说,欢乐颂第一季,yy玄幻小说排行榜完本

首頁 > 開發 > 綜合 > 正文

Linux啟動過程綜述

2024-07-21 02:38:25
字體:
來源:轉載
供稿:網友

  作者:楊沙洲
  
  文以Redhat 6.0 linux 2.2.19 for Alpha/AXP為平臺,描述了從開機到登錄的 Linux 啟動全過程。該文對i386平臺同樣適用。
  一. Bootloader
  在Alpha/AXP平臺上引導Linux通常有兩種方法,一種是由MILO及其他類似的引導程序引導,另一種是由Firmware直接引導。MILO功能與i386平臺的LILO相近,但內置有基本的磁盤驅動程序(如IDE、SCSI等),以及常見的文件系統驅動程序(如ext2,iso9660等), firmware有ARC、SRM兩種形式,ARC具有類BIOS界面,甚至還有多重引導的設置;而SRM則具有功能強大的命令行界面,用戶可以在控制臺上使用boot等命令引導系統。ARC有分區(Partition)的概念,因此可以訪問到分區的首扇區;而SRM只能將控制轉給磁盤的首扇區。兩種firmware都可以通過引導MILO來引導Linux,也可以直接引導Linux的引導代碼。
  
  “arch/alpha/boot”下就是制作Linux Bootloader的文件。“head.S”文件提供了對 OSF PAL/1的調用入口,它將被編譯后置于引導扇區(ARC的分區首扇區或SRM的磁盤0扇區),得到控制后初始化一些數據結構,再將控制轉給“main.c”中的start_kernel(), start_kernel()向控制臺輸出一些提示,調用pal_init()初始化PAL代碼,調用openboot() 打開引導設備(通過讀取Firmware環境),調用load()將核心代碼加載到START_ADDR(見 “include/asm-alpha/system.h”),再將Firmware中的核心引導參數加載到ZERO_PAGE(0) 中,最后調用runkernel()將控制轉給0x100000的kernel,bootloader部分結束。
  
  “arch/alpha/boot/bootp.c”以“main.c”為基礎,可代替“main.c”與“head.S” 生成用于BOOTP協議網絡引導的Bootloader。
  Bootloader中使用的所有“srm_”函數在“arch/alpha/lib/”中定義。
  
  以上這種Boot方式是一種最簡單的方式,即不需其他工具就能引導Kernel,前提是按照 Makefile的指導,生成bootimage文件,內含以上提到的bootloader以及vmlinux,然后將 bootimage寫入自磁盤引導扇區始的位置中。
  
  當采用MILO這樣的引導程序來引導Linux時,不需要上面所說的Bootloader,而只需要 vmlinux或vmlinux.gz,引導程序會主動解壓加載內核到0x1000(小內核)或0x100000(大內核),并直接進入內核引導部分,即本文的第二節。
  
  對于I386平臺
  i386系統中一般都有BIOS做最初的引導工作,那就是將四個主分區表中的第一個可引導分區的第一個扇區加載到實模式地址0x7c00上,然后將控制轉交給它。
  
  在“arch/i386/boot”目錄下,bootsect.S是生成引導扇區的匯編源碼,它首先將自己拷貝到0x90000上,然后將緊接其后的setup部分(第二扇區)拷貝到0x90200,將真正的內核代碼拷貝到0x100000。以上這些拷貝動作都是以bootsect.S、setup.S以及vmlinux在磁盤上連續存放為前提的,也就是說,我們的bzImage文件或者zImage文件是按照bootsect,setup, vmlinux這樣的順序組織,并存放于始于引導分區的首扇區的連續磁盤扇區之中。
  
  bootsect.S完成加載動作后,就直接跳轉到0x90200,這里正是setup.S的程序入口。 setup.S的主要功能就是將系統參數(包括內存、磁盤等,由BIOS返回)拷貝到 0x90000-0x901FF內存中,這個地方正是bootsect.S存放的地方,這時它將被系統參數覆蓋。以后這些參數將由保護模式下的代碼來讀取。
  
  除此之外,setup.S還將video.S中的代碼包含進來,檢測和設置顯示器和顯示模式。最后,setup.S將系統轉換到保護模式,并跳轉到0x100000(對于bzImage格式的大內核是 0x100000,對于zImage格式的是0x1000)的內核引導代碼,Bootloader過程結束。
  
  對于2.4.x版內核
  沒有什么變化。
  
  二.Kernel引導入口
  
  
  在arch/alpha/vmlinux.lds的鏈接腳本控制下,鏈接程序將vmlinux的入口置于 "arch/alpha/kernel/head.S"中的__start上,因此當Bootloader跳轉到0x100000時, __start處的代碼開始執行。__start的代碼很簡單,只需要設置一下全局變量,然后就跳轉到start_kernel去了。start_kernel()是"init/main.c"中的asmlinkage函數,至此,啟動過程轉入體系結構無關的通用C代碼中。
  
  
  對于I386平臺
  在i386體系結構中,因為i386本身的問題,在"arch/alpha/kernel/head.S"中需要更多的設置,但最終也是通過call SYMBOL_NAME(start_kernel)轉到start_kernel()這個體系結構無關的函數中去執行了。

  
  所不同的是,在i386系統中,當內核以bzImage的形式壓縮,即大內核方式(__BIG_KERNEL__)壓縮時就需要預先處理bootsect.S和setup.S,按照大核模式使用$(CPP) 處理生成bbootsect.S和bsetup.S,然后再編譯生成相應的.o文件,并使用 "arch/i386/boot/comPRessed/build.c"生成的build工具,將實際的內核(未壓縮的,含 kernel中的head.S代碼)與"arch/i386/boot/compressed"下的head.S和misc.c合成到一起,其中的head.S代替了"arch/i386/kernel/head.S"的位置,由Bootloader引導執行(startup_32入口),然后它調用misc.c中定義的decompress_kernel()函數,使用 "lib/inflate.c"中定義的gunzip()將內核解壓到0x100000,再轉到其上執行 "arch/i386/kernel/head.S"中的startup_32代碼。
  
  對于2.4.x版內核
  沒有變化。
  
  三.核心數據結構初始化--內核引導第一部分
  start_kernel()中調用了一系列初始化函數,以完成kernel本身的設置。這些動作有的是公共的,有的則是需要配置的才會執行的。
  
  在start_kernel()函數中,
  輸出Linux版本信息(printk(linux_banner))
  設置與體系結構相關的環境(setup_arch())
  頁表結構初始化(paging_init())
  使用"arch/alpha/kernel/entry.S"中的入口點設置系統自陷入口(trap_init())
  使用alpha_mv結構和entry.S入口初始化系統IRQ(init_IRQ())
  核心進程調度器初始化(包括初始化幾個缺省的Bottom-half,sched_init())
  時間、定時器初始化(包括讀取CMOS時鐘、估測主頻、初始化定時器中斷等,time_init())
  提取并分析核心啟動參數(從環境變量中讀取參數,設置相應標志位等待處理,(parse_options())
  控制臺初始化(為輸出信息而先于PCI初始化,console_init())
  剖析器數據結構初始化(prof_buffer和prof_len變量)
  核心Cache初始化(描述Cache信息的Cache,kmem_cache_init())
  延遲校準(獲得時鐘jiffies與CPU主頻ticks的延遲,calibrate_delay())
  內存初始化(設置內存上下界和頁表項初始值,mem_init())
  創建和設置內部及通用cache("slab_cache",kmem_cache_sizes_init())
  創建uid taskcount SLAB cache("uid_cache",uidcache_init())
  創建文件cache("files_cache",filescache_init())
  創建目錄cache("dentry_cache",dcache_init())
  創建與虛存相關的cache("vm_area_strUCt","mm_struct",vma_init())
  塊設備讀寫緩沖區初始化(同時創建"buffer_head"cache用戶加速訪問,buffer_init())
  創建頁cache(內存頁hash表初始化,page_cache_init())
  創建信號隊列cache("signal_queue",signals_init())
  初始化內存inode表(inode_init())
  創建內存文件描述符表("filp_cache",file_table_init())
  檢查體系結構漏洞(對于alpha,此函數為空,check_bugs())
  SMP機器其余CPU(除當前引導CPU)初始化(對于沒有配置SMP的內核,此函數為空,smp_init())
  啟動init過程(創建第一個核心線程,調用init()函數,原執行序列調用cpu_idle() 等待調度,init())
  至此start_kernel()結束,基本的核心環境已經建立起來了。
  
  
  對于I386平臺
  i386平臺上的內核啟動過程與此基本相同,所不同的主要是實現方式。
  
  對于2.4.x版內核
  2.4.x中變化比較大,但基本過程沒變,變動的是各個數據結構的具體實現,比如Cache。
  
  四.外設初始化--內核引導第二部分
  init()函數作為核心線程,首先鎖定內核(僅對SMP機器有效),然后調用 do_basic_setup()完成外設及其驅動程序的加載和初始化。過程如下:
  
  總線初始化(比如pci_init())
  網絡初始化(初始化網絡數據結構,包括sk_init()、skb_init()和proto_init()三部分,在proto_init()中,將調用protocols結構中包含的所有協議的初始化過程,sock_init())
  創建bdflush核心線程(bdflush()過程常駐核心空間,由核心喚醒來清理被寫過的內存緩沖區,當bdflush()由kernel_thread()啟動后,它將自己命名為kflushd)
  創建kupdate核心線程(kupdate()過程常駐核心空間,由核心按時調度執行,將內存緩沖區中的信息更新到磁盤中,更新的內容包括超級塊和inode表)
  設置并啟動核心調頁線程kswapd(為了防止kswapd啟動時將版本信息輸出到其他信息中間,核心線調用kswapd_setup()設置kswapd運行所要求的環境,然后再創建 kswapd核心線程)
  創建事件治理核心線程(start_context_thread()函數啟動context_thread()過程,
并重命名為keventd)
  設備初始化(包括并口parport_init()、字符設備chr_dev_init()、塊設備 blk_dev_init()、SCSI設備scsi_dev_init()、網絡設備net_dev_init()、磁盤初始化及分區檢查等等,device_setup())
  執行文件格式設置(binfmt_setup())
  啟動任何使用__initcall標識的函數(方便核心開發者添加啟動函數,do_initcalls())
  文件系統初始化(filesystem_setup())
發表評論 共有條評論
用戶名: 密碼:
驗證碼: 匿名發表
主站蜘蛛池模板: 略阳县| 龙井市| 民勤县| 台东县| 金溪县| 宁蒗| 长顺县| 沁源县| 德安县| 江孜县| 阿巴嘎旗| 宾阳县| 兴海县| 留坝县| 武穴市| 西和县| 鱼台县| 镶黄旗| 旬阳县| 农安县| 贵州省| 佳木斯市| 保靖县| 土默特左旗| 民权县| 道真| 铁岭市| 离岛区| 吕梁市| 乡城县| 双柏县| 申扎县| 秭归县| 闸北区| 长治县| 惠东县| 娄烦县| 周口市| 尉氏县| 中江县| 施秉县|