第二个startup_32( )函数完成的功能
解压缩Linux内核的工作由另外一个startup_32( )函数来完成。该函数位于/usr/src/linux-2.4.2/arch/i386/kernel/head.S文件中。
这时你可能会说两个不同的函数用同一个名字不会出错吗?答案是不会的。因为两个函数都是到自己初始地址去执行,并且都有自己的执行环境,所以不会出错。
下面我们来看一下第二个startup_32( )函数的功能。当执行这个函数时,实际上是为第一个Linux进程(process 0)设置环境。这个函数将执行下面的操作:
(1)段寄存器将以最后的值进行初始化;
(2)为process 0设置内核模式栈;
(3)调用并且执行setup_idt( )函数,该函数将把所有的IDT填充空值;
(4)把从BIOS中获得的参数放在第一页的框架中;
(5)识别处理器的模式;
(6)使用GDT和IDT表加载gdtr和idtr寄存器;
(7)最后跳到start_kernel( )函数。
start_kernel( )函数功能
start_kernel( )函数完成Linux内核的初始化工作。这个函数执行后,所有的基本内核组件都将被初始化。这也是整个启动过程的最后一步。
该函数将完成以下的功能:
(1)执行paging_init( )函数初始化页表(Page Tables);
(2)执行mem_init( )函数初始化页描述符(Page Descriptors);
(3)执行trap_init( ) 和 init_IRQ( )函数,最后一次对IDT进行初始化;
(4)执行kmem_cache_init( )和kmem_cache_sizes_init ( )函数,对Slab Allocator进行初始化;
(5)执行time_init( )函数,初始化系统日期和时间;
(6)内核的线程process 1是通过调用kernel_thread( )来完成的。接着就建立其它的内核线程并且执行/sbin/init程序。
到此屏幕上就会显示“Linux version 2.4.2 ……”信息。此外,还会显示很多其它信息。最后,就会出现用户的登录提示符。这是在告诉用户Linux内核已经加载完成,用户已经可以使用。
总结
到现在为止,整个启动过程都已经描述完毕。其中提到的许多词汇我都没有解释,只简要说了一下IDT、GDT、eip寄存器和cs寄存器等。