linux内核启动流程
时间:11-22
来源:互联网
点击:
1.3 parse_options()
分析由内核引导程序发送给内核的启动选项,在初始化过程中按照某些选项运行,并将剩余部分传送给init进程。这些选项可能已经存储在配置文件中,也可能是由用户在系统启动时敲入的。但内核并不关心这些,这些
细节都是内核引导程序关注的内容,嵌入式系统更是如此。
1.4 trap_init() (/kernel/traps.c do_trap)
这个函数用来做体系相关的中断处理的初始化,在该函数中调用__trap_init((void *)vectors_base())函数将exception vector设置到vectors_base开始的地址上。 __trap_init函数位于entry-armv.S文
件中,对于ARM处理器,共有复位、未定义指令、SWI、预取终止、数据终止、IRQ和FIQ 几种方式。SWI主要
用来实现系统调用,而产生了IRQ之后,通过exception vector进入中断处理过程,执行do_IRQ函数。
armnommu的trap_init()函数在arch/armnommu/kernel/traps.c文件中。vectors_base是写中断向
量的开始地址,在include/asm-armnommu/proc-armv/system.h文件中设置,地址为0或0XFFFF0000。
[plain]view plaincopyprint?
- ENTRY(__trap_init)
- stmfdsp!,{r4-r6,lr}
- mrsr1,cpsr@codefrom2.0.38
- bicr1,r1,#MODE_MASK@clearmodebits/*设置svc模式,disableIRQ,FIQ*/
- orrr1,r1,#I_BIT|F_BIT|MODE_SVC@setSVCmode,disableIRQ,FIQ
- msrcpsr,r1
- adrr1,.LCvectors@setupthevectors
- ldmiar1,{r1,r2,r3,r4,r5,r6,ip,lr}
- stmiar0,{r1,r2,r3,r4,r5,r6,ip,lr}/*拷贝异常向量*/
- addr2,r0,#0x200
- adrr0,__stubs_start@copystubsto0x200
- adrr1,__stubs_end
- 1:ldrr3,[r0],#4
- strr3,[r2],#4
- cmpr0,r1
- blt1b
- LOADREGS(fd,sp!,{r4-r6,pc})
1.5 init_IRQ()
[cpp]view plaincopyprint?
- void__initinit_IRQ(void)
- {
- externvoidinit_dma(void);
- intirq;
- for(irq=0;irq
- irq_desc[irq].probe_ok=0;
- irq_desc[irq].valid=0;
- irq_desc[irq].noautoenable=0;
- irq_desc[irq].mask_ack=dummy_mask_unmask_irq;
- irq_desc[irq].mask=dummy_mask_unmask_irq;
- irq_desc[irq].unmask=dummy_mask_unmask_irq;
- }
- CSR_WRITE(AIC_MDCR,0x7FFFE);/*disableallinterrupts*/
- CSR_WRITE(CAHCNF,0x0);/*CloseCache*/
- CSR_WRITE(CAHCON,0x87);/*FlushCache*/
- while(CSR_READ(CAHCON)!=0);
- CSR_WRITE(CAHCNF,0x7);/*OpenCache*/
- init_arch_irq();
- init_dma();
- }
一个irq_desc结构,组成了一个数组。NR_IRQS代表中断数目,这里只是对中断结构irq_desc进行了初始
化。在默认的初始化完成后调用初始化函数init_arch_irq,先执行arch/armnommu/kernel/irq-
arch.c文件中的函数genarch_init_irq(),然后就执行 include/asm-armnommu/arch-xxxx/irq.h中
的inline函数irq_init_irq,在这里对irq_desc进行了实质的初始化。其中mask用阻塞中断;unmask用
来取消阻塞;mask_ack的作用是阻塞中断,同时还回应ack给硬件表示这个中断已经被处理了,否则硬件将再
次发生同一个中断。这里,不是所有硬件需要这个ack回应,所以很多时候mask_ack与mask用的是同一个函
数。
接下来执行init_dma()函数,如果不支持DMA,可以设置include/asm-armnommu/arch-xxxx/dma.h中
的 MAX_DMA_CHANNELS为0,这样在arch/armnommu/kernel/dma.c文件中会根据这个定义使用不同的函
数。
1.6 sched_init()
初始化系统调度进程,主要对定时器机制和时钟中断的Bottom Half的初始化函数进行设置。与时间相关的初始化过程主要有两步:(1)调用 init_timervecs()函数初始化内核定时器机制;(2)调用init_bh()函
数将BH向量TIMER_BH、TQUEUE_BH和 IMMEDIATE_BH所对应的BH函数分别设置成timer_bh()、
tqueue_bh()和immediate_bh()函数
1.7 softirq_init()
内核的软中断机制初始化函数。调用tasklet_init初始化tasklet_struct结构,软中断的个数为32个。用于bh的 tasklet_struct结构调用tasklet_init()以后,它们的函数指针func全都指向bh_action()。
bh_action就是tasklet实现bh机制的代码,但此时具体的bh函数还没有指定。
HI_SOFTIRQ用于实现bottom half,TASKLET_SOFTIRQ用于公共的tasklet。
open_softirq(TASKLET_SOFTIRQ, tasklet_action, NULL); /* 初始化公共的tasklet_struct要
用到的软中断 */
open_softirq(HI_SOFTIRQ, tasklet_hi_action, NULL); /* 初始化tasklet_struct实现的
bottom half调用 */
1.
linux内核启动流 相关文章:
- ARM Linux内核启动流程(11-21)
- Windows CE 进程、线程和内存管理(11-09)
- RedHatLinux新手入门教程(5)(11-12)
- uClinux介绍(11-09)
- openwebmailV1.60安装教学(11-12)
- Linux嵌入式系统开发平台选型探讨(11-09)