长篇连载--arm linux演艺---第八回 -------------------------------------------------------------------------------- 上回我们讲到arm靠初始化完成了,打开了cache,到此为止,汇编部分的初始化代码就差不多了,最后还有几件事情做: 1。初始化BSS段,全部清零,BSS是全局变量区域。 2。保存与系统相关的信息:如 .long SYMBOL_NAME(compat) .long SYMBOL_NAME(__bss_start) .long SYMBOL_NAME(_end) .long SYMBOL_NAME(processor_id) .long SYMBOL_NAME(__machine_arch_type) .long SYMBOL_NAME(cr_alignment) .long SYMBOL_NAME(init_task_union)+8192 不用讲,大家一看就明白意思 3。重新设置堆栈指针,指向init_task的堆栈。init_task是系统的第一个任务,init_task的堆栈在task structure的后8K,我们后面会看到。 4。最后就要跳到C代码的start_kernel。 b SYMBOL_NAME(start_kernel) 现在让我们来回忆一下目前的系统状态: 临时页表已经建立,在0X08004000处,映射了4M,虚地址0XC000000被映射到0X08000000. CACHE,MMU都已经打开。 堆栈用的是任务init_task的堆栈。 如果以为到了c代码可以松一口气的话,就大错特措了,linux的c也不比汇编好懂多少,相反到掩盖了汇编的一些和机器相关的部分,有时候更难懂。其实作为编写操作系统的c代码,只不过是汇编的另一种写法,和机器代码的联系是很紧密的。 start_kernel在 /linux/init/main.c中定义: asmlinkage void __init start_kernel(void) { char * command_line; unsigned long mempages; extern char saved_command_line[]; lock_kernel(); printk(linux_banner); setup_arch(&command_line); //arm/kernel/setup.c printk("Kernel command line: %s ", saved_command_line); parse_options(command_line); trap_init(); // arm/kernle/traps.c install 。。。。。。。。。 start_kernel中的函数个个都是重量级的,首先用printk(linux_banner);打出系统版本号,这里面就大有文章,系统才刚开张,你让他打印到哪里去呢?先给大家交个底,以后到console的部分自然清楚,printk和printf不同,他首先输出到系统的一个缓冲区内,大约4k,如果登记了 console,则调用console->wirte函数输出,否则就一直在buffer里呆着。所以,用printk输出的信息,如果超出了 4k,会冲掉前面的。在系统引导起来后,用dmesg看的也就是这个buffer中的东东。 arm linux 待续。。。。。
|