基于PXAxxx平台的Andriod(Linux kernel 2.6.29)内核移植到Meego(linux kernel 2.6.35)过程二

来源:互联网 发布:大数据理论研究 编辑:程序博客网 时间:2024/05/29 15:17

接下来介绍main.c 中的start_kernel()函数

asmlinkage void __init start_kernel(void)

{

            char *command_line;

            externstruct kernel_param __start___param[], __stop___param[];

printk(KERN_NOTICE"<lujiado>smp_setup_processor_id->start/n");

            smp_setup_processor_id();

 

//   当只有一个CPU的时候这个函数就什么也不做,所以就把它定义为空,但是如//果有多个CPU的时候那么它就返回在启动的时候的那个CPUID,而这个函数//在配置了多CPU的时候是有定义的。

//

 

printk(KERN_NOTICE"<lujiado>smp_setup_processor_id->end/n");

 

            /*

             * Need to run as early as possible, toinitialize the

             * lockdep hash:

             */

            lockdep_init();

// lockdep_init();
//    定义在include/linux/lockdep.h文件中
//  //       define lockdep_init()                       do { } while (0)
 //    它是一个宏,什么也不做

 

            debug_objects_early_init();

/*

* Set up the the initial canary ASAP:

*第四个函数是debug_objects_early_init()
   //定义在include/linux/debugobjects.h文件中
   //static inline void debug_objects_early_init(void) { }
   ///   它是个内联函数,什么也不做

*/

            boot_init_stack_canary();

 

            cgroup_init_early();

 

// cgroup_init_early();
//     它定义在include/linux/cgroup.h

 //     static  inline intcgroup_init_early(void) { return 0; }
 //    它是一个内联函数,什么也不做

 

            local_irq_disable();

 

//它定义在include/asm-alpha/system.h文件中
//        #define  local_irq_disable()               do {setipl(IPL_MAX);barrier();  } while(0)
   //     它是一个宏,执行setipl(IPL_MAX);barrier()函数,其中IPL_MAX7//setipl()也是宏,也在该文件中定义,为:#define
 //       setipl(ipl)            ((void)
///        swpipl(ipl)),而barrier()定义在arch/powerpc/boot/io.h文件中,为:
 ///       static
 ///       inline void barrier(void)
 ///      
////        {
 ////      
 ///      
////                asm
 ////       volatile("" : : :"memory");
       
 ////       }   
    ////    用于实现内存屏蔽

 

            early_boot_irqs_off();

/*它定义在文件include/linux/lockdep.h中,为:static
        inline void early_boot_irqs_off(void) {}
        是一个内联函数,什么也不做*/

 

            early_init_irq_lock_class();

    /*  它定义在文件include/linux/lockdep.h中,为:static
        inline void early_init_irq_lock_class(void){}
        是个内联函数,什么也不做*/

 

/*

 * Interrupts arestill disabled. Do necessary setups, then

 * enable them

 */

            lock_kernel();

 

 

 

            tick_init();

            boot_cpu_init();

/*

lock_kernel()定义在文件include/linux/smp_lock.h中,为:

#define lock_kernel()                 do { } while(0)是个宏,什么也不做
 tick_init()定义在文件include/linux/tick.h,为:

staticinline void tick_init(void) { }是个内联函数,什么也不做
  boot_cpu_init();定义在文件init/main.c函数中,它定义为:
        static
        void __init boot_cpu_init(void)
       
        {
                int
        cpu = smp_processor_id();
                /*
        Mark the boot cpu "present","online" etc for
        SMP and UP case */
                cpu_set(cpu,cpu_online_map);
                cpu_set(cpu, cpu_present_map);
                cpu_set(cpu, cpu_possible_map);
       
        }
        它企图激活第一个处理器,其中函数smp_processor_id()定义在include/linux/smp.h文件中,它返回当前CPU
        ID,定义为:
        #ifdef
        CONFIG_DEBUG_PREEMPT
            extern unsigned intdebug_smp_processor_id(void);
        #
        define smp_processor_id() debug_smp_processor_id()
        #else
        #
        define smp_processor_id() raw_smp_processor_id()
        #endif
        如果DEBUG_PREEMPT使能的话,我们需检查它是否在安全抢占模式下,一般当它使用在非抢占临界区或一个和当前CPU绑定的线程上,它是安全的,ram_smp_processor_id()只在内部使用,它是一个宏定义,为:#define
        raw_smp_processor_id()           0

*/

            page_address_init();

/*

page_address_init(),它定义在include/linux/mm.h,也是一个宏,实现:#define
        page_address_init()  do { } while(0),什么也不做
        [*]然后是打印语句printk(KERN_NOTICE);其中KERN_NOTICE定义在文件include/linux/kernel.h中,实现如下:
        #define
        KERN_EMERG      ""   /* system is unusable      
                   */
        #define
        KERN_ALERT        ""   /* action must be taken
        immediately     */
        #define
        KERN_CRIT           ""   /* critical conditions
                       */
        #define
        KERN_ERR            ""   /* error conditions   
                       */
        #define
        KERN_WARNING    ""  /* warning conditions      
                  */
        #define
        KERN_NOTICE      ""   /* normal but significant
        condition     */
        #define
        KERN_INFO           ""   /* informational     
                       */
        #define
        KERN_DEBUG       ""   /* debug-level messages   
                    */
        [*]然后打印语句printk(linux_banner);
        其中linux_banner定义在init/version.c中,具体定义如下:
        /*
        FIXED STRINGS! Don't touch! */
        const
        char linux_banner[] =
                "Linux
        version " UTS_RELEASE " ("LINUX_COMPILE_BY "@"
               LINUX_COMPILE_HOST
        ") (" LINUX_COMPILER ") "UTS_VERSION "/n";

*/

            printk(KERN_NOTICE"%s", linux_banner);

            setup_arch(&command_line);/*初始化内存*/
                                                //返回内核参数和内核可用的物理地址范围

            printk(KERN_NOTICE"init start_kernel()->setup_arch end/n ");

            mm_init_owner(&init_mm,&init_task);// //空函数 /include/linux/sched.h                                         /kernel/fork.c 实现

            printk(KERN_NOTICE"init start_kernel()->mm_init_owner end/n ");

            setup_command_line(command_line);

//保存命令行,以备后用,此保存空间需申请

//这个函数调用完了,就开始执行下面初始化函数

 

            printk(KERN_NOTICE"init start_kernel()->setup_command_line() end/n ");

            setup_nr_cpu_ids();        //空函数

            setup_per_cpu_areas();//设置每个CPU的信息,单核CPU为空函数

            smp_prepare_boot_cpu();        /* arch-specific boot-cpu hooks */

//设置启动的CPU为在线状态.在多CPU架构下

//第一个启动的cpu启动到一定阶段后,开始启动其它的cpu,它会为每个后来启动的cpu创建一个0号进程,而这些0号进程的堆栈的thread_info结构中的cpu成员变量则依次被分配出来(利用alloc_cpu_id()函数)并设置好,这样当这些cpu开始运行的时候就有了自己的逻辑cpu号。

 

 

            build_all_zonelists(NULL);////建立内存区域链表

            page_alloc_init();//内存页初始化,此处无执行

 

            printk(KERN_NOTICE"Kernel command line: %s/n", boot_command_line);

            parse_early_param();//没有解释

            parse_args("Bootingkernel", static_command_line, __start___param,

                           __stop___param - __start___param,

                           &unknown_bootoption);

            /*

             * These use large bootmem allocations and mustprecede

             * kmem_cache_init()

             */

            pidhash_init();//进程哈希表初始化

            vfs_caches_init_early();//建立节点哈希表和数据缓冲哈希表           sort_main_extable();////对异常处理函数进行排序

            trap_init();  //初始化硬件中断 /arch/i386/kernel/traps.c文件里定义此函数

            mm_init();

            /*

             * Set up the scheduler prior starting anyinterrupts (such as the

             * timer interrupt). Full topology setuphappens at smp_init()

             * time - but meanwhile we still have afunctioning scheduler.

             */

            sched_init();//初始化调度/kernel/sched.c文件里有详细的调度算法(这些会       

                                ///在以后进程管理和调度的结构分析中详细介绍)

            /*

             * Disable preemption - early bootup schedulingis extremely

             * fragile until we cpu_idle() for the firsttime.

             */

            preempt_disable();////启动阶段系统比较脆弱,禁止进程调度

            if(!irqs_disabled()) {

                        printk(KERN_WARNING"start_kernel(): bug: interrupts were "

                                                "enabled*very* early, fixing it/n");

                        local_irq_disable();

            }

            rcu_init();//linux2.6的一种互斥访问机制

            radix_tree_init();

            /* initsome links before init_ISA_irqs() */

            early_irq_init();

            init_IRQ();//中断向量初始化

            prio_tree_init();////初始化优先级数组

            init_timers();///定时器初始化

            hrtimers_init();///高精度时钟初始化

            softirq_init();//软中断初始化

            timekeeping_init();////系统时间初始化

            time_init();

            profile_init();//空函数

            if(!irqs_disabled())

                        printk(KERN_CRIT"start_kernel(): bug: interrupts were "

                                                 "enabled early/n");

            early_boot_irqs_on();

            local_irq_enable();

 

            /*Interrupts are enabled now so all GFP allocations are safe. */

            gfp_allowed_mask= __GFP_BITS_MASK;

 

            kmem_cache_init_late();

 

            /*

             * HACK ALERT! This is early. We're enablingthe console before

             * we've done PCI setups etc, andconsole_init() must be aware of

             * this. But we do want output early, in casesomething goes wrong.

             */

            console_init();//打印终端初始化

            if(panic_later)

                        panic(panic_later,panic_param);

 

            lockdep_info();

 

            /*

             * Need to run this when irqs are enabled,because it wants

             * to self-test [hard/soft]-irqs on/off lockinversion bugs

             * too:

             */

            locking_selftest();

 

#ifdef CONFIG_BLK_DEV_INITRD

            if(initrd_start && !initrd_below_start_ok &&

                page_to_pfn(virt_to_page((void*)initrd_start)) < min_low_pfn) {

                        printk(KERN_CRIT"initrd overwritten (0x%08lx < 0x%08lx) - "

                            "disabling it./n",

                            page_to_pfn(virt_to_page((void*)initrd_start)),

                            min_low_pfn);

                        initrd_start= 0;

            }

#endif

            page_cgroup_init();

            enable_debug_pagealloc();

            kmemtrace_init();

            kmemleak_init();

            debug_objects_mem_init();

            idr_init_cache();//创建idr缓冲区

            setup_per_cpu_pageset();//采用的是一致性内存,此函数为空

            numa_policy_init();//采用的是一致性内存,此函数为空

            if(late_time_init)

                        late_time_init();

            sched_clock_init();

            calibrate_delay();//校准延时函数的精确度,实际上是校准loops_per_jiffy全局变量,即每个时钟滴答内CPU执行的指令数

            pidmap_init();//进程号位图初始化,一般用一个page来指示所有的进程PID占用情况           

anon_vma_init();//空函数

#ifdef CONFIG_X86

            if(efi_enabled)

                        efi_enter_virtual_mode();

#endif

            thread_info_cache_init();//空函数

            cred_init();

            fork_init(totalram_pages);//初始化kernelfork()环境。Linux下应用程序执行是靠系统调用fork()完成,fork_init所完成的工作就是确定可以fork()的线程的数量,然后是初始化init_task进程

            proc_caches_init();//proc文件系统创建高速缓存            buffer_init();

            key_init();();//没有键盘则为空,如果有键盘,则为键盘分配一个高速缓存

            security_init();//空函数 dbg_late_init();

            vfs_caches_init(totalram_pages);//虚拟文件系统挂载,这个函数的是重点,需要研究一下。 

            signals_init();////创建并初始化信号队列

            /* rootfspopulating might need page-writeback */

            page_writeback_init();//CPU在内存中开辟高速缓存,CPU直接访问高速缓存提以高速度。当cpu更新了高速缓存的数据后,需要定期将高速缓存的数据写回到存储介质中,比如磁盘和flash等。这个函数初始化写回的周期

#ifdef CONFIG_PROC_FS

            proc_root_init();////如果配置了proc文件系统,则需初始化并加载proc文件系统。在根目录的proc文件夹就是proc文件系统,这个文件系统是ram类型的,记录系统的临时数据,系统关机后不会写回到flash

#endif

            cgroup_init();//没有配置cgroup,此函数为空

            cpuset_init();//CPU,此函数为空

            taskstats_init_early();//进程状态初始化,实际上就是分配了一个存储线程状态的高速缓存

            delayacct_init();//空函数

            check_bugs();//空函数

 

            acpi_early_init();/* before LAPIC and SMP init *///空函数

            sfi_init_late();

 

            ftrace_init();          

 

            /* Do therest non-__init'ed, we're now alive */

            rest_init();

}


原创粉丝点击