内核启动过程

android:     有图形界面
linux      没有图形界面

出错关键字: panic(恐慌)

内核启动:
    第一阶段:head.S (无打印调试信息)
    第二阶段 main.c 
         start ----- > start_kernal(void)
                     starting kernel、内核版本;
        1 建立平台相关的代码  --->setup_arch( )
                     CPU、时钟、内存 (cpu构架 、机器信息、 cpu信息、时钟(高速、低速分频)、firmware时钟初始化、内存的布局 
        2 初始化linux相关的初始化  ---> 进程、文件、信号、中断
        3 执行所以的设备驱动 -----------|
        4 挂载根文件系统       -----------|-------rest_init(  )
        5 执行祖先进程           -----------|
                    设备驱动(i2c_adapter)--tcp/udp --网络协议
rest_init( ); 
starting kernel  --->  内核版本 --->cpu构架 ---> 机器信息 ---> cpu信息 ---> 
时钟(高速、低速分频) ---> firmware时钟初始化 ---> 内存的布局 ---> 进程、网络、文件、
中断、信号 ---> 设备驱动(i2c_adapter)--->tcp/udp ---> 网络协议

3. 内核内部构造和内核启动

第一阶段不打印调试信息--> head.S
第二阶段: init/main.c
    start_kernel()
        |
        printk(KERN_NOTICE "%s", linux_banner);
        setup_arch(&command_line); //建立架构平台相关代码--cpu,时钟初始化,内存的初始化
            |
            struct machine_desc *mdesc;
            mdesc = setup_machine_tags(machine_arch_type);
                        |//在.arch.info.init中找到对应的结构体,用指针指向
                        for (p = __arch_info_begin; p < __arch_info_end; p++)
            machine_desc = mdesc;


        // 解析uboot传递过来的bootargs中的所有的参数 root=xxx console=xxx  init=xxx  nfsroot=xxx
        //有一个应用--bootargs中参数是可以自定义set bootargs console=ttySAC0,115200  myname=ruhua myage=18
        // 如果在内核中需要去获取到参数的值, 该怎么办--__setup()
        printk(KERN_NOTICE "Kernel command line: %s\n", boot_command_line);
        parse_early_param();
        parse_args("Booting kernel", static_command_line, __start___param,
               __stop___param - __start___param,
               &unknown_bootoption); 


        //中间部分为linux基本的初始化, 进程,线程,信号,调度器,中断,下半部等
        //此处省略n多行

        rest_init();
            |//smdkv210_machine_init在这个函数执行的
            启动三个内核线程
            kernel_thread(kernel_init, NULL, CLONE_FS | CLONE_SIGHAND);
                kernel_init()
                        |
                        1, do_basic_setup();//执行所有驱动的入口函数,执行.initcallx.init
                                |
                                do_initcalls();
                                    |
                                    initcall_t *fn;
                                    for (fn = __early_initcall_end; fn < __initcall_end; fn++)
                                        do_one_initcall(*fn);
                                            |
                                            ret = fn();//调用了所有的函数指针,就是调用所有驱动的入口
                        2,prepare_namespace();//挂载根文件系统
                        3,init_post();//执行第一个用户进程
                            |
                            if (execute_command) {// init=/linuxrc, execute_command=="/linuxrc"
            //优先执行init=xx传递的, 指定的init进程
                                run_init_process(execute_command);
                                printk(KERN_WARNING "Failed to execute %s.  Attempting "
                                            "defaults...\n", execute_command);
                            }
                            run_init_process("/sbin/init");
                            run_init_process("/etc/init");
                            run_init_process("/bin/init");
                            run_init_process("/bin/sh");

                            panic("No init found.  Try passing init= option to kernel. "
                                  "See Linux Documentation/init.txt for guidance.");

            kernel_thread(kthreadd, NULL, CLONE_FS | CLONE_FILES);
                         kthreadd()//用来创建其他的线程
            schedule();//主线程 睡觉


mach-smdkv210.c
MACHINE_START(SMDKV210, "FS210") //包含了一个id, MACHINE_START实际是一个结构体, struct machine_desc
    /* Maintainer: Kukjin Kim <kgene.kim@samsung.com> */
    .boot_params    = S5P_PA_SDRAM + 0x100,
    .init_irq   = s5pv210_init_irq,
    .map_io     = smdkv210_map_io,
    .init_machine   = smdkv210_machine_init,
    .timer      = &s5p_timer,
MACHINE_END


#define MACHINE_START(_type,_name)          \
static const struct machine_desc __mach_desc_##_type    \
 __used                         \
 __attribute__((__section__(".arch.info.init"))) = {    \
    .nr     = MACH_TYPE_##_type,        \
    .name       = _name,

#define MACHINE_END             \
};
===>
整个结构体都会编译到.arch.info.init
static const struct machine_desc __mach_desc_SMDKV210 __attribute__((__section__(".arch.info.init"))) ={
    .nr     = MACH_TYPE_SMDKV210,// 2456    
    .name       = "FS210",
    .boot_params    = S5P_PA_SDRAM + 0x100,
    .init_irq   = s5pv210_init_irq,
    .map_io     = smdkv210_map_io,
    .init_machine   = smdkv210_machine_init,
    .timer      = &s5p_timer,
};
解释--为什么smdkv210_machine_init(void)是在开机的时候执行
     __arch_info_begin = .; //起始位置
       *(.arch.info.init)//机器信息段
      __arch_info_end = .; //结束位置

只需要知道.arch.info.init -->整个结构体__mach_desc_SMDKV210
    知道结构体就可以调用函数指针:init_machine()
        调用函数指针就实际调用了smdkv210_machine_init();




static int __init myname_setup(char *str)
{

    printk("----^_^myname = %s ------\n", str);

    return 1;//正常放回
}

__setup("myname=", myname_setup);

static int __init myage_setup(char *str)
{
    int age = simple_strtoul(str, NULL, 10);

    printk("----^_^myage = %d ------\n", age);

    return 1;//正常放回
}

__setup("myage=", myage_setup);

出错处理:
Starting kernel ...

Uncompressing Linux... done, booting the kernel.

原因:
1, console=xx设置错误
2, uboot传递machid出错
3, 内核在编译:
        (0) S3C UART to use for low-level messages 
        // 内核的调试信息需要由ttySAC0打印出来,这个要和bootargs中的console=xx保持一致
  • 0
    点赞
  • 1
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值