Arm linux kernel 启动之start_kernel
说实话启动的代码看到现在唯一的感觉就是kernel的全局变量实在太多了,要了解一个过程跟踪一个变量的值的变化相当痛苦啊,不过耐心看下来,收获还是比较丰富的,对很多概念都有了一个比较直观的理解。闲话就不多说了,直接来上代码~~
smp_setup_processor_id();
//这个函数现在是空的;
lockdep_init();
//Runtime locking correctness validator, see Documentation/lockdep_design.txt
debug_objects_early_init();
cgroup_init_early();
//Control group, read Documentation/cgroup.txt
local_irq_disable();
//使用armcpsid i指令来禁止IRQ
early_boot_irqs_off();
early_init_irq_lock_class();
/* 基本上面几个函数就是初始化lockdep和cgroup,然后禁止IRQ,为后续的运行创造条件 */
lock_kernel();
/* 看这个函数的之前我们首先来了解一段知识,linux kernel默认是支持preemption(抢占)的。在SMP环境下为了实现kernel的锁定,kernel使用了一个BKL(big kernel lock)的概念,在初始化的过程中先锁定这个BKL,然后再继续进行其他启动或者初始化过程,这样就可以防止启动过程中被中断,执行到res_init以后,kernel会释放这个锁,这样就确保了整个start_kernel过程都不会被抢占或者中断。由此我们可以看到这主要是针对多处理器而言的,实际上如果只有一个处理器的话它也不会被中断或者被抢占。 */
/* 下面我们来看看这个函数的执行过程,在这里面能学到很多东西的:
int depth = current->lock_depth+1;
这个current实际上是一个宏,定义在arch/arm/include/asm/current.h里面,它实际是一个task_struct的结构体,这个结构体描述了这个task的一系列信息(task应该是linux进程调度的一个基本单位?)。linux下每个进程都有一个相对应的task_struct,这个task_struct有几个我们经常能看到的信息,一个就是PID,然后就是comm进程的名字,然后就是mm_struct,它定义了跟这个进程相关的所有申请的memory的管理。这个curren_thread_info()也是个很有意思的函数,直接读取SP来获得当前线程的结构体信息thread_info。thread_info和task_struct这两个结构体应该就代表了当前线程的所有信息。
初始化的lock_depth是-1,只有init task的lock_depth是0。
if (likely(!depth))
__lock_kernel();
这里判断是不是init task,如果是就会执行__lock_kernel();这个__lock_kernel首先禁止抢占,然后试着获得BKL,如果成功则直接返回,如果不成功首先判断是否禁止抢占成功了,如果成功了就用自旋锁去锁BKL。如果禁止抢占没有成功则在抢占有效的情况下去等待BKL,直到获得BKL。因为QC的片子不是SMP,所有这里第一次try的时候就直接成功了。
current->lock_depth = depth;
这个就没什么好说的了 */
/* 基本上来说这个lock_kernel就是禁止抢占,然后获得BKL,干了这么件事 */
tick_init();
//和时钟相关的初始化,好像是注册notify事件,没有仔细研究过
boot_cpu_init();
//这个实际上是在SMP环境下选择CPU,这里直接CPUID选择的是0号cpu
page_address_init();
//初始化high memory,在arm环境下实际上这个函数是空的,也就是说arm不支持high memory
printk(KERN_NOTICE);
printk(linux_banner);
//这里的KER_NOTICE是字符串<5>,不太明白它的意思。。。后面的linux_banner定义在kernel/init/version.c里面,这里的printk是门高深的学问,以后看console的时候会仔细分析
setup_arch(&command_line);
/* 这是一个重量级的函数了,会比较仔细地分析一下,主要完成了4个方面的工作,一个就是取得MACHINE和PROCESSOR的信息然或将他们赋值给kernel相应的全局变量,然后呢是对boot_command_line和tags接行解析,再然后呢就是memory、cach的初始化,最后是为kernel的后续运行请求资源。 */
/* 我们来仔细看看这个函数的实现:
setup_processor();
这个函数首先从arm寄存器里面取得cpu ID,然后调用lookup_processor_t
Armlinuxkerne 相关文章:
- Android arm linux kernel启动流程一(11-09)
- Android arm linux kernel启动流程二(11-09)
- Arm Linux Kernel 构建 情景分析(11-09)
- Android arm linux kernel启动流程(11-09)
- arm linux kernel 从入口到start_kernel 的代码分析(11-09)
- Windows CE 进程、线程和内存管理(11-09)