日韩性视频-久久久蜜桃-www中文字幕-在线中文字幕av-亚洲欧美一区二区三区四区-撸久久-香蕉视频一区-久久无码精品丰满人妻-国产高潮av-激情福利社-日韩av网址大全-国产精品久久999-日本五十路在线-性欧美在线-久久99精品波多结衣一区-男女午夜免费视频-黑人极品ⅴideos精品欧美棵-人人妻人人澡人人爽精品欧美一区-日韩一区在线看-欧美a级在线免费观看

歡迎訪問 生活随笔!

生活随笔

當前位置: 首頁 > 运维知识 > linux >内容正文

linux

linux内核唤醒过程,Linux内核启动过程分析

發布時間:2025/3/20 linux 26 豆豆
生活随笔 收集整理的這篇文章主要介紹了 linux内核唤醒过程,Linux内核启动过程分析 小編覺得挺不錯的,現在分享給大家,幫大家做個參考.

1、Linux內核啟動協議

閱讀文檔\linux-2.6.35\Documentation\x86\boot.txt

傳統支持Image和zImage內核的啟動裝載內存布局(2.4以前的內核裝載就是這樣的布局):

|? ? ? ? ? ? |

0A0000? ? +------------------------+

|? Reserved for BIOS? ? |? ? Do not use.? Reserved for BIOS EBDA.

09A000? ? +------------------------+

|? Command line? ? ? ? |

|? Stack/heap? ? ? ? |? ? For use by the kernel real-mode code.

098000? ? +------------------------+

|? Kernel setup? ? ? ? |? ? The kernel real-mode code.

090200? ? +------------------------+

|? Kernel boot sector? ? |? ? The kernel legacy boot sector.

090000? ? +------------------------+

|? Protected-mode kernel |? ? The bulk of the kernel image.

010000? ? +------------------------+

|? Boot loader? ? ? ? |? ?

001000? ? +------------------------+

|? Reserved for MBR/BIOS |

000800? ? +------------------------+

|? Typically used by MBR |

000600? ? +------------------------+

|? BIOS use only? ? |

000000? ? +------------------------+

當使用bzImage時,保護模式的內核會被重定位到0x1000000(高端內存),內核實模式的代碼(boot sector,setup和stack/heap)會被編譯成可重定位到0x100000與低端內存底端之間的任何地址處。不幸的是,在2.00和2.01版的引導協議中,0x90000+的內存區域仍然被使用在內核的內部。2.02版的引導協議解決了這個問題。boot loader應該使BIOS的12h中斷調用來檢查低端內存中還有多少內存可用。

人們都希望“內存上限”,即boot loader觸及的低端內存最高處的指針,盡可能地低,因為一些新的BIOS開始分配一些相當大的內存,所謂的擴展BIOS數據域,幾乎快接近低端內存的最高處了。

不幸的是,如果BIOS 12h中斷報告說內存的數量太小了,則boot loader除了報告一個錯誤給用戶外,什么也不會做。因此,boot loader應該被設計成占用盡可能少的低端內存。對zImage和以前的bzImage,這要求數據能被寫到x090000段,boot loader應該確保不會使用0x9A000指針以上的內存;很多BIOS在這個指針以上會終止。

對一個引導協議>=2.02的現代bzImage內核,其內存布局使用以下格式:

|? Protected-mode kernel |

100000? +------------------------+

|? I/O memory hole? ? |

0A0000? ? +------------------------+

|? Reserved for BIOS? ? |? ? Leave as much as possible unused

~? ? ? ? ? ? ? ? ? ? ? ? ~

|? Command line? ? ? ? |? ? (Can also be below the X+10000 mark)

X+10000? ? +------------------------+

|? Stack/heap? ? ? ? |? ? For use by the kernel real-mode code.

X+08000? ? +------------------------+

|? Kernel setup? ? ? ? |? ? The kernel real-mode code.

|? Kernel boot sector? ? |? ? The kernel legacy boot sector.

X? ? ? +------------------------+

|? Boot loader? ? ? ? |? ?

001000? ? +------------------------+

|? Reserved for MBR/BIOS |

000800? ? +------------------------+

|? Typically used by MBR |

000600? ? +------------------------+

|? BIOS use only? ? |

000000? ? +------------------------+

這里程序段地址是由grub的大小來決定的。地址X應該在bootloader所允許的范圍內盡可能地低。

2、BIOS POST過程

傳統意義上,由于CPU加電之后,CPU只能訪問ROM或者RAM里的數據,而這個時候是沒有計算機操作系統的,所以需要有一段程序能夠完成加載存儲在非易失性存儲介質(比如硬盤)上的操作系統到RAM中的功能。這段程序存儲在ROM里,BIOS就是這類程序中的一種。對于BIOS,主要由兩家制造商制造,駐留在主板的ROM里。有了BIOS,硬件制造商可以只需要關注硬件而不需要關注軟件。BIOS的服務程序,是通過調用中斷服務程序來實現的。BIOS加載bootloader程序,Bootloader也可以通過BIOS提供的中斷,向BIOS獲取系統的信息。整個過程如下:

(1)電源啟動時鐘發生器并在總線上產生一個#POWERGOOD的中斷。

(2)產生CPU的RESET中斷(此時CPU處于8086工作模式)。

(3)進入BIOS POST代碼處:%ds=%es=%fs=%gs=%ss=0,%cs=0xFFFF0000,%eip = 0x0000FFF0 (ROM BIOS POST code,指令指針eip,數據段寄存器ds,代碼段寄存器cs)。

(4)在中斷無效狀態下執行所有POST檢查。

(5)在地址0初始化中斷向量表IVT。

(6)0x19中斷:以啟動設備號為參數調用BIOS啟動裝載程序。這個程序從啟動設備(硬盤)的0扇面1扇區讀取數據到內存物理地址0x7C00處開始裝載。這個0扇面1扇區稱為Boot sector(引導扇區),共512字節,也稱為MBR。

就是說,CPU 在? BIOS 的入口(CS:IP=FFFF:0000)處執行BIOS的匯編程序,BIOS程序功能有系統硬件的檢測,提供中斷訪問接口以訪問硬件。而后被BIOS程序通過中斷0x19調用磁盤MBR上的bootloader程序,將bootloader程序加載到ox7c00處,而后跳轉到0x7c00,這樣,位于 0x7c00處的bootloader程序,就可以執行了。

從BIOS執行MBR中的bootloader程序開始,就是linux的代碼在做的事情了。

3、Bootloader過程

bootloader程序是為計算機加載(load)計算機操作系統的。boot(引導)是bootstrap的簡寫,bootstrap是引導指令的意思。bootloader程序通常位于硬盤上,被BIOS調用,用于加載內核。在PC機上常見的bootloader主要有grub、lilo、syslinux等。

GRUB(GRand Unified Bootloader)是當前linux諸多發行版本默認的引導程序。嵌入式系統上,最常見的bootloader是U-BOOT。這樣的bootloader一般位于MBR的最前部。在linux系統中,bootloader也可以寫入文件系統所在分區中。比如,grub程序就非常強大。Gurb運行后,將初始化設置內核運行所需的環境。然后加載內核鏡像。

grub磁盤引導全過程:

(1)stage1: grub讀取磁盤第一個512字節(硬盤的0道0面1扇區,被稱為MBR(主引導記錄),也稱為bootsect)。MBR由一部分bootloader的引導代碼、分區表和魔數三部分組成。

(2)stage1_5: 識別各種不同的文件系統格式。這使得grub識別到文件系統。

(3)stage2: 加載系統引導菜單(/boot/grub/menu.lst或grub.lst),加載內核vmlinuz和RAM磁盤initrd。

4、內核啟動過程

內核映像文件vmlinuz:包含有linux內核的靜態鏈接的可執行文件,傳統上,vmlinux被稱為可引導的內核鏡像。vmlinuz是vmlinux的壓縮文件。其構成如下:

(1)第一個512字節(以前是在arch/i386/boot/bootsect.S);

(2)第二個,一段代碼,若干個不多于512字節的段(以前是在arch/i386/boot/setup.S);

(3)保護模式下的內核代碼(在arch/x86/boot/main.c)。

bzImage文件:使用make bzImage命令編譯內核源代碼,可以得到采用zlib算法壓縮的zImage文件,即big zImage文件。老的zImage解壓縮內核到低端內存,bzImage則解壓縮內核到高端內存(1M(0x100000)以上),在保護模式下執行。bzImage文件一般包含有vmlinuz、bootsect.o、setup.o、解壓縮程序misc.o、以及其他一些相關文件(如piggy.o)。注意,在Linux 2.6內核中,bootsect.S和setup.S被整合為header.S。

initramfs(或initrd)文件:initrd是initialized ram disk的意思。主要用于加載硬件驅動模塊,輔助內核的啟動,掛載真正的根文件系統。

例如,我電腦上的grub啟動項如下(在/boot/grub/grub.lst中):

title Fedora (2.6.35.10-74.fc14.i686)

root (hd0,0)

kernel /vmlinuz-2.6.35.10-74.fc14.i686 ro root=/dev/mapper/VolGroup-lv_root rd_LVM_LV=VolGroup/lv_root rd_LVM_LV=VolGroup/lv_swap rd_NO_LUKS rd_NO_MD rd_NO_DM LANG=zh_CN.UTF-8 KEYBOARDTYPE=pc KEYTABLE=us rhgb quiet

initrd /initramfs-2.6.35.10-74.fc14.i686.img

內核的執行參數可以控制內核的行為,比如ro參數告訴內核,以只讀方式掛載根分區,而quiet則告訴內核,啟動的時候不要打印任何信息。這些參數不光影響內核的執行,大多數的發行版也使用這些參數控制啟動完畢以后后續的動作。這些參數可以在任何時候從/proc/cmdline 這個文件中獲得。現在,grub找到了內核(hd0,0)/boot/vmlinuz-2.6.35.10-74.fc14.i686,它將整個電腦的控制權交給了這個程序,內核開始進行各種初始化的動作,你可以將quiet參數去掉,以便看看內核都做了哪些事情,也可以在系統啟動成功以后,使用dmesg這個命令查看內核啟動的時候,都打印了哪些東西。

啟動過程是和體系結構相關的,對于2.6內核,x86體系結構,CPU在上電初始化時,指令寄存器CS:EIP總是被初始化為固定值,這就是CPU復位后的第一條指令的地址。對于32位地址總線的系統來說,4GB的物理空間至少被劃分為兩個部分,一部分是內存的地址空間,另外一部分地址空間用于對BIOS芯片存儲單元進行尋址。x86復位后工作在實模式下,該模式下CPU的尋址空間為1MB。CS:IP的復位值是FFFF:0000,物理地址為FFFF0。主板設計者必須保證把這個物理地址映射到BIOS芯片上,而不是RAM上。

裝載Linux內核的第一步應該是加載實模式代碼(boot sector和setup代碼),然后檢查偏移0x01f1處的頭部(header)中的各個參數值。實模式的代碼總共有32K,但是boot loader可以選擇只裝載前面的兩個扇區(1K),然后檢查bootup扇區的大小。

header���各個域的格式如下:

Offset/Size? Proto? Name? ? Meaning

01F1/1? ALL(1? setup_sects? The size of the setup in sectors

01F2/2? ALL? root_flags? ? If set, the root is mounted readonly

01F4/4? 2.04+? syssize? ? The size of the 32-bit code in 16-byte paras

01F8/2? ALL? ram_size? DO NOT USE - for bootsect.S use only

01FA/2? ALL? vid_mode? Video mode control

01FC/2? ALL? root_dev? Default root device number

01FE/2? ALL? boot_flag? 0xAA55 magic number

0200/2? 2.00+? jump? ? Jump instruction

0202/4? 2.00+? header? ? Magic signature "HdrS"

0206/2? 2.00+? version? ? Boot protocol version supported

0208/4? 2.00+? realmode_swtch? Boot loader hook (see below)

020C/2? 2.00+? start_sys_seg? The load-low segment (0x1000) (obsolete)

020E/2? 2.00+? kernel_version? Pointer to kernel version string

0210/1? 2.00+? type_of_loader? Boot loader identifier

0211/1? 2.00+? loadflags? Boot protocol option flags

0212/2? 2.00+? setup_move_size? Move to high memory size (used with hooks)

0214/4? 2.00+? code32_start? Boot loader hook (see below)

0218/4? 2.00+? ramdisk_image? initrd load address (set by boot loader)

021C/4? 2.00+? ramdisk_size? initrd size (set by boot loader)

0220/4? 2.00+? bootsect_kludge? DO NOT USE - for bootsect.S use only

0224/2? 2.01+? heap_end_ptr? Free memory after setup end

0226/1? 2.02+? ext_loader_ver? Extended boot loader version

0227/1? 2.02+? ext_loader_type? Extended boot loader ID

0228/4? 2.02+? cmd_line_ptr? 32-bit pointer to the kernel command line

022C/4? 2.03+? ramdisk_max? Highest legal initrd address

0230/4? 2.05+? kernel_alignment? Physical addr alignment required for kernel

0234/1? 2.05+? relocatable_kernel? Whether kernel is relocatable or not

0235/1? 2.10+? min_alignment? Minimum alignment, as a power of two

0236/2? N/A? pad3? ? ? ? ? Unused

0238/4? 2.06+? cmdline_size? Maximum size of the kernel command line

023C/4? 2.07+? hardware_subarch? Hardware subarchitecture

0240/8? 2.07+? hardware_subarch_data? Subarchitecture-specific data

0248/4? 2.08+? payload_offset? Offset of kernel payload

024C/4? 2.08+? payload_length? Length of kernel payload

0250/8? 2.09+? setup_data? 64-bit physical pointer to linked list of struct setup_data

0258/8? 2.10+? pref_address? Preferred loading address

0260/4? 2.10+? init_size? Linear memory required during initialization

總結

以上是生活随笔為你收集整理的linux内核唤醒过程,Linux内核启动过程分析的全部內容,希望文章能夠幫你解決所遇到的問題。

如果覺得生活随笔網站內容還不錯,歡迎將生活随笔推薦給好友。