Mr. Process的一生-Linux内核的社会视角 (2)启动
http://www.manio.org/cn/startup-of-linux-view-of-society.html
其實這才應該是這一系列文章的第一節,因為這篇文章講的是盤古開天地的事。話說Mr. Process是一個現代人,但是,只要是人,總該有個祖先。人們總想知道自己從哪來,然后才可以估摸算一下自己將去向何方。所以咱也要了解一下Linux的世界里人類的起源。
圖1:從上電到BIOS
按下電源開關的那個真實的人就是Linux世界里的上帝,他創造了Linux世界的一切。當他按下機箱上的電源開關時,主板開始供電,CPU上的Reset Pin被拉高,這會引起CPU的一系列動作,這些動作是芯片設計時就決定的。CPU中的一些寄存器被置為固定的值,因為這些寄存器可能在啟動的過程中要使用,比如CS(代碼段寄存器)和EIP(指針指令寄存器)。這一步完成之后,CPU就可開執行地址為0xfffffff0里的ROM中的程序。這段程序就是BIOS(Basic Input Output System)。
BIOS完成下面的功能:
1.POST(Power-On Self Test):顧名思名,就是查查有什么設備,這些設備是不是正常。要是CPU有Advanced Configuration and Power Interface(ACPI )的支持,也在這個時候進行。ACPI是用來對電源進行管理的,用來節電之類的。
2.初始化設備:確保沒有IRQ和IO沖突。
3.尋找OS/Bootloader。這一步后面點再細說
我們在BIOS的設置菜單里能夠設置從何處啟動,比如軟盤,硬盤,光驅…BIOS會按我們設定的順序搜索OS。
4.把Bootloader復制到RAM里(地址為0x00007c00),然后那個地址開始執行。
什么是Bootloader?
現在,我們只要關心的是:bootloader會找到OS,把OS內核COPY到RAM中。
圖2:boot loader的加載
如上圖所示,在硬盤的第一個sector,有一個分區表(記錄了哪些分區上有操作系統)和一個小版的Bootloader。當這個BIOS被設置為從這里啟動時,這個小版的bootloader被復制到RAM的0x00007c00。然后它會把自己又移動到0x00096a00。在這之后,它再把另一段Bootloader從硬盤上復制到0x00096c00,然后從那里開始執行。分作兩段的原因是因為現在的bootloader太大了,在MBR上存不完那么多。
Bootloader會把OS的內核映像復制到RAM中。
Bootloader的工作
1. 調用BIOS以顯示“Loading Image”的消息。
2. 調用BIOS,把內核映像的前512字節復制到0×00090000,setup()函數在0×00090200。
3. 調用BIOS,把剩下的內核映像加載到0×00010000(小內核zImage)或0×00100000(大內核bzImage)
4. 跳到setup()開始執行。
Setup()的工作
setup()用來初始化設備。雖然BIOS已經做了一些初始化的工作,但是Linux關不依賴于他。setup()會初始化鍵盤,FPU等設備,并設置一些寄存器。在Setup()的最后,會調用startup_32()。
startup_32()
Linux里有兩個startup_32()。
首先會執行的是arch/i386/boot/compressed/head.S里的那個。這個startup_32()的作用主要是解壓內核。
第二個startup_32()是在arch/i386/kernel/head.S的。這個startup_32()的工作就是為Linux的第一個進程(就是Mr. Process的祖先)設置生存環境。最后跳到start_kernel()中去。
在Understanding the Linux Kernel 3rd 中的描述如下
- Initializes the segmentation registers with their final values.
- Fills the bss segment of the kernel (see the section “Program Segments and Process Memory Regions” in Chapter 20) with zeros.
- Initializes the provisional kernel Page Tables contained in swapper_pg_dir and pg0 to identically map the linear addresses to the same physical addresses, as explained in the section “Kernel Page Tables” in Chapter 2.
- Stores the address of the Page Global Directory in the cr3 register, and enables paging by setting the PG bit in the cr0 register.
- Sets up the Kernel Mode stack for process 0 (see the section “Kernel Threads” in Chapter 3).
- Once again, the function clears all bits in the eflags register.
- Invokes setup_idt( ) to fill the IDT with null interrupt handlers (see the section “Preliminary Initialization of the IDT” in Chapter 4).
- Puts the system parameters obtained from the BIOS and the parameters passed to the operating system into the first page frame (see the section “Physical Memory Layout” in Chapter 2).
- Identifies the model of the processor.
10.? Loads the gdtr and idtr registers with the addresses of the GDT and IDT tables.
11.? Jumps to the start_kernel( ) function.
start_kernel()的工作
完成所有組件的初始化工作。
Understanding the Linux Kernel對這一段工作的描述如下:
¨??? The scheduler is initialized by invoking the sched_init( ) function (see Chapter 7).
¨??? The memory zones are initialized by invoking the build_all_zonelists( ) function (see the section “Memory Zones” in Chapter 8).
¨??? The Buddy system allocators are initialized by invoking the page_alloc_init( ) and mem_init( ) functions (see the section “The Buddy System Algorithm” in Chapter 8).
¨??? The final initialization of the IDT is performed by invoking trap_init( ) (see the section “Exception Handling” in Chapter 4) and init_IRQ( ) (see the section “IRQ data structures” in Chapter 4).
¨??? The TASKLET_SOFTIRQ and HI_SOFTIRQ are initialized by invoking the softirq_init( ) function (see the section “Softirqs” in Chapter 4).
¨??? The system date and time are initialized by the time_init( ) function (see the section “The Linux Timekeeping Architecture” in Chapter 6).
¨??? The slab allocator is initialized by the kmem_cache_init( ) function (see the section “General and Specific Caches” in Chapter 8).
¨??? The speed of the CPU clock is determined by invoking the calibrate_delay( ) function (see the section “Delay Functions” in Chapter 6).
¨??? The kernel thread for process 1 is created by invoking the kernel_thread( ) function. In turn, this kernel thread creates the other kernel threads and executes the /sbin/init program, as described in the section “Kernel Threads” in Chapter 3.
以上幾個函數的執行過程如下圖:
圖3:啟動函數的執行過程
第二個startup_32()和start_kernel()揭示了Linux一生的真諦。從這里面咱看到了Mr. Process(一個普通的進程)所擁有的一切是怎么得到的。弄清楚了這些,也就弄清楚了Linux。Really清楚。
BTW,我做的圖怎么那么好看~美感天生在那里,你擋都擋不住,怎么搞怎么好看加專業!
總結
以上是生活随笔為你收集整理的Mr. Process的一生-Linux内核的社会视角 (2)启动的全部內容,希望文章能夠幫你解決所遇到的問題。
- 上一篇: 英寸的计算方法?
- 下一篇: IANA定义的常见服务的端口号列表