uclinux很久前笔记8

本文深入探讨了基于ARM架构的Linux内核启动过程,详细分析了从汇编引导到C语言环境的转换,以及关键初始化步骤,如内存管理、中断处理等。

摘要生成于 C知道 ,由 DeepSeek-R1 满血版支持, 前往体验 >

【分析linux启动】

arch/armnommu/vmlinux.lds(vmlinux-armv.lds.in生成):

OUTPUT_ARCH(arm)
ENTRY(stext)
SECTIONS
{
       . = 0x0c008000;   //链接地址(由TEXTADDR参数传递来的)。
       .init: {                  /* Init code and data             */
              _stext= .;
              __init_begin= .;
                     *(.text.init)
              __proc_info_begin= .;
                     *(.proc.info)
……
}

arch/armnommu/kernel/head- armv.s

.section".text.init",#alloc,#execinstr
              .type       stext, #function
ENTRY(stext)
              b          99f                /* 0x00 reset vector */
              b     vector_undefinstr   /* 0x04 undefined instruction */
              b     vector_swi             /*0x08 software interrupt */
              b     vector_prefetch      /* 0x0C prefetch abort */
              b     vector_data            /*0x10 data abort */
              b     vector_addrexcptn  /* 0x14 address exception */
              b     vector_IRQ            /*0x18 IRQ */
              b     vector_FIQ            /*0x1C FIQ */
99:
mov r12, r0
              ……
              mov r0, #F_BIT | I_BIT | MODE_SVC       @ make sure svc mode
              msr  cpsr_c, r0                                          @ and all irqs disabled
              #ifdefined(CONFIG_CPU_S3C3410) || defined(CONFIG_CPU_S3C4530) || \
defined(CONFIG_CPU_S3C44B0X)
                adr     r2, LC0
                @  Copy data sections to their new home
                ldmia   r2, {r4-r11,sp}
                cmp     r9, r11
                beq     2f
1:              cmp     r11, r10
                ldrcc   r3, [r9], #4
                strcc   r3, [r11], #4
                bcc     1b
              @ clear BSS
2:              mov     r3, #0
3:              cmp     r7, r8
                strcc   r3, [r7], #4
                bcc     3b
#if defined(CONFIG_CPU_S3C44B0X)
              ldr   r9, =S3C44B0X_SYSCFG
              ldr   r3, [r9]
              orr   r3, r3, #0xe
              str    r3, [r9]    @enablecache and write buffer
 
              ldr   r3,S3C44B0X_PROCESSOR_TYPE   //0x44B044B0
              str    r3, [r5]
             
              mov r3, #MACH_TYPE_S3C44B0X
              str    r3, [r6]
#endif
                mov     fp, #0
                b      start_kernel

//经过实践证明汇编程序从这里跳转到start_kernel中,位于 init/main.c中,下面的相关处理程序是在c语言中完成的。

                            b .          //在该处加入该语句内核可以正常启动。

//加在b  start_kernel之前则不能启动内核。

#if defined(CONFIG_CPU_S3C44B0X)
S3C44B0X_PROCESSOR_TYPE:
              .long       0x44B044B0
#endif
在include/asm-arm/mach-types.h中定义:
#define MACH_TYPE_S3C44B0              178   
// u-boot中传递的bd->bi_arch_number参数值要与这个值一致。
LC0:
#if defined(CONFIG_CPU_S3C3410) || defined(CONFIG_CPU_S3C44B0X)
                .long   0x07ff0000                 @r4
#endif
                .long   processor_id                 @ r5
                .long   __machine_arch_type         @r6
                .long   __bss_start                  @r7   bss start
                .long   _end                      @ r8   bss end
                            ……
.long   _end_romfs                @r9   data start in ROM (src)
……
                .long   _edata                     @ r10  data end in RAM
                .long   __data_start                  @r11  data start in RAM (dst)
.long  init_task_union+8192          @ sp
……
              bl    __lookup_processor_type
              teq   r10, #0                         @invalid processor?
              moveq     r0, #'p'                   @yes, error 'p'
              beq  __error
              bl    __lookup_architecture_type
#if !defined(CONFIG_ARCTURUS)
              teq   r7, #0                           @invalid architecture?
              moveq     r0, #'a'                   @yes, error 'a'
              beq  __error
#endif
#ifndef CONFIG_UCLINUX
              bl    __create_page_tables
#endif
              adr   lr, __ret                 @return address
              add  pc, r10, #12           @ initialise processor
                                                 @(return control reg)
 
__switch_data:       .long       __mmap_switched
              .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
 
__ret:             ldr   lr, __switch_data
              mov pc, lr
__mmap_switched:
              adr   r3, __switch_data + 4
              ldmia      r3, {r2, r4, r5, r6, r7, r8, sp}@ r2 =compat
                                                        @ sp = stack pointer
              str    r12, [r2]
 
              mov fp, #0                           @Clear BSS (and zero fp)
1:           cmp r4, r5
              strcc fp, [r4],#4
              bcc  1b
 
              str    r9, [r6]                  @Save processor ID
              str    r1, [r7]                  @Save machine type
#ifdef CONFIG_ALIGNMENT_TRAP
              orr   r0, r0, #2               @...........A.
#endif
              bic   r2, r0, #2               @Clear 'A' bit
              stmia       r8, {r0, r2}     @ Save control register values
              b     SYMBOL_NAME(start_kernel)  //跳转到init/main.c中
asmlinkage void __init start_kernel(void)
{
       ……
       lock_kernel();
       printk(linux_banner);
       setup_arch(&command_line);
       printk("Kernelcommand line: %s\n", saved_command_line);
       parse_options(command_line);
       trap_init();
       init_IRQ();
       sched_init();
       softirq_init();
       time_init();
console_init();
       ……
rest_init();
}
static void rest_init(void)
{
       kernel_thread(init, NULL, CLONE_FS | CLONE_FILES |CLONE_SIGNAL);
       unlock_kernel();
       current->need_resched= 1;
      cpu_idle();
}
static int init(void* unused)
{
       ……
       if(execute_command)
       {
              printk("printtest---->>>>  execute_command\n");
              run_init_process(execute_command);
       }
       printk("print test---->>>>  /sbin/init\n");    //只有改行打印信息被输出
       run_init_process("/sbin/init");                            //说明只有改行语句被执行
       printk("printtest---->>>> /etc/init\n");
       run_init_process("/etc/init");
       printk("printtest---->>>> /bin/init\n");
       run_init_process("/bin/init");
       printk("printtest---->>>> /bin/sh\n");
       run_init_process("/bin/sh");  
panic("Noinit found.  Try passing init= option tokernel.");
}
static void run_init_process(char*init_filename)
{
       argv_init[0]= init_filename;               //此时的argv_init[0]=/sbin/init”的
       if(argv_init[1])
       {
              printk("run_init_process---->>>> argv_init[1] = 1\n");
              printk("%s.\n", argv_init[1]);
       }
       else
       {
              printk("run_init_process---->>>> argv_init[1] = 0\n"); //该信息被打印
              strcpy(argv_init[1], "/etc/rc");    // argv_init[1]这个参数没有用上,更改后不影响。
       }
       execve(init_filename,argv_init, envp_init);
}
static void __init parse_options(char*line)   //line= command_line
{
       ……
       if(!strncmp(line,"init=",5)) {//在解析没有空格的字符串中有”init=”字符串时,将init=后字符串赋值给execute_command,如:”init=/bin/sh”。
              line+= 5;
              execute_command = line;
              args= 0;
              continue;
       }
       ……
       if(*line)
              argv_init[++args] = line;
       ……
       argv_init[args+1]= NULL;
envp_init[envs+1]= NULL;
}
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值