Linux kernel

 

1、uboot引导kernel:
      u-boot中有个bootm命令,它可以引导内存中的应用程序映像(Kernel),bootm命令对应
common/cmd_bootm.c中的do_bootm()函数,此函数实现下面几个功能:
    1)读flash中的内核映像文件
    2)解压内核
    3)校验内核
    4)跳到内核执行(调用do_bootm_linux()函数)

    {

转自:

图片 1

图片 2

实现了uboot对非linux
kernel的引导。虽然有一个IH_TYPE_STANDALONE,但是没有实现。nnd。只能自己想办法。实现详细见下面。

1、Stage1 start.S代码结构 u-boot的stage1代码通常放在start.S文件中,他用汇编语言写成,其主要代码部分如下

1、uboot引导kernel:
      u-boot中有个bootm命令,它可以引导内存中的应用程序映像(Kernel),bootm命令对应
common/cmd_bootm.c中的do_bootm()函数,此函数实现下面几个功能:
    1)读flash中的内核映像文件
    2)解压内核
    3)校验内核
    4)跳到内核执行(调用do_bootm_linux()函数)

    {

Linux logo

图片 3

1、两个命令

 

1、Stage1 start.S代码结构 u-boot的stage1代码通常放在start.S文件中,他用汇编语言写成,其主要代码部分如下

图片 4

set bootcmd tftp 84000000 uImage;bootm 84000000

(1) 定义入口。: 

 

图片 5

set bootdelay 1

该工作通过修改连接器脚本来完成。

(1) 定义入口。: 

图片 6

2、非linux kernel的引导实现方法:

(2)设置异常向量(Exception Vector)。 

该工作通过修改连接器脚本来完成。

图片 7

一共三个函数: jump,selectboot 和 system_boot

(3)设置CPU的速度、时钟频率及终端控制寄存器。 

(2)设置异常向量(Exception Vector)。 

图片 8

把jump放在需要跳转的地方,参数就是要跳转的地址。然后返回,重启系统。select放在main的开头。通过判断ram的特定地址的特定信息实现跳转。

(4)初始化内存控制器。 

(3)设置CPU的速度、时钟频率及终端控制寄存器。 

system_boot实现系统的重新启动

(5)将ROM中的程序复制到RAM中。 

(4)初始化内存控制器。 

#define FDMA_SRAM_TOP_ADDRESS 0xB9229800
#define MAGIC_NUM 0x71097100
#define DEAD_PATTERN 0xBAD0BADF
#define ST40_CPG_REGS_BASE 0xFFC00000#define
ST40_CPG_WTCNT (ST40_CPG_REGS_BASE + 0x08)
#define ST40_CPG_WTCSR (ST40_CPG_REGS_BASE + 0x0C)
#define ST40_CPG_WTCSR2 (ST40_CPG_REGS_BASE + 0x1C)
void Jump(unsigned int address)
{
STSYS_WriteRegDev32LE(FDMA_SRAM_TOP_ADDRESS - 4*1, MAGIC_NUM);
STSYS_WriteRegDev32LE(FDMA_SRAM_TOP_ADDRESS - 4*2, address);
STSYS_WriteRegDev32LE(FDMA_SRAM_TOP_ADDRESS - 4*3, ~address);
STSYS_WriteRegDev32LE(FDMA_SRAM_TOP_ADDRESS - 4*4, ~MAGIC_NUM); 
STSYS_WriteRegDev16LE(ST40_CPG_WTCNT, 0x5AF0); /*Watchdog counter*/
STSYS_WriteRegDev16LE(ST40_CPG_WTCSR, 0xA547); /*Watchdog control*/
STSYS_WriteRegDev16LE(ST40_CPG_WTCSR2, 0xAA00); /*Watchdog control2*/ 
STSYS_WriteRegDev16LE(ST40_CPG_WTCSR, 0xA5C7); /*Start watchdog counter*/ for(;;);
}
void SelectBoot(void)
{
unsigned int MagicNum = 0;
unsigned int NotMagicNum = 0;
unsigned int JumpAddress = 0;
unsigned int NotJumpAddress = 0; void (*entry)(void);
/* entry=0xa0100000;
entry();*/ //if((STSYS_ReadRegDev16LE(ST40_CPG_WTCSR2) & 0xFF) != 0x0)
{
MagicNum = STSYS_ReadRegDev32LE(FDMA_SRAM_TOP_ADDRESS - 4*1);
JumpAddress = STSYS_ReadRegDev32LE(FDMA_SRAM_TOP_ADDRESS - 4*2);
NotJumpAddress = STSYS_ReadRegDev32LE(FDMA_SRAM_TOP_ADDRESS - 4*3);
NotMagicNum = STSYS_ReadRegDev32LE(FDMA_SRAM_TOP_ADDRESS - 4*4); 
if((MagicNum == MAGIC_NUM)
&& (MagicNum == (~NotMagicNum))
&& (JumpAddress == (~NotJumpAddress)))
{
entry = (void (*)(void))JumpAddress;
STSYS_WriteRegDev32LE(FDMA_SRAM_TOP_ADDRESS - 4*1, DEAD_PATTERN);
STSYS_WriteRegDev32LE(FDMA_SRAM_TOP_ADDRESS - 4*2, DEAD_PATTERN);
STSYS_WriteRegDev32LE(FDMA_SRAM_TOP_ADDRESS - 4*3, DEAD_PATTERN);
STSYS_WriteRegDev32LE(FDMA_SRAM_TOP_ADDRESS - 4*4, DEAD_PATTERN); 
#if 0/*Setup For watchdog in case jump failed.*/
STSYS_WriteRegDev16LE(ST40_CPG_WTCNT, 0x5AF0);
STSYS_WriteRegDev16LE(ST40_CPG_WTCSR, 0xA543);
STSYS_WriteRegDev16LE(ST40_CPG_WTCSR2, 0xAA01); 
STSYS_WriteRegDev16LE(ST40_CPG_WTCSR, 0xA5C7);
#endif entry(); while(1);
}
}
}void system_reboot(void)
{
ulong sr;
asm ("stc sr, %0":"=r" (sr));
sr |= (1 << 28); /* set block bit */
asm ("ldc %0, sr": :"r" (sr));
asm volatile ("trapa #0");
}

(6)初始化堆栈。 

(5)将ROM中的程序复制到RAM中。 

kernel的引导。虽然有一个IH_TYPE_STANDALONE,但是没有实现。nnd。只能自己想办法。实现详细见下面。
1、两个命令 set boo…

(7)转到RAM中执行,该工作可使用指令ldr pc来完成。

(6)初始化堆栈。 

 

(7)转到RAM中执行,该工作可使用指令ldr pc来完成。

2、Stage2 C语言代码部分 lib_arm/board.c中的start arm boot是C语言开始的函数也是整个启动代码中C语言的主函数,同时还是整个u-boot(armboot)的主函数,该函数只要完成如下操作: 

 

(1)调用一系列的初始化函数。 

2、Stage2 C语言代码部分 lib_arm/board.c中的start arm boot是C语言开始的函数也是整个启动代码中C语言的主函数,同时还是整个u-boot(armboot)的主函数,该函数只要完成如下操作: 

(2)初始化Flash设备。 

(1)调用一系列的初始化函数。 

(3)初始化系统内存分配函数。 

(2)初始化Flash设备。 

(4)如果目标系统拥有NAND设备,则初始化NAND设备。 

(3)初始化系统内存分配函数。 

(5)如果目标系统有显示设备,则初始化该类设备。 

(4)如果目标系统拥有NAND设备,则初始化NAND设备。 

(6)初始化相关网络设备,填写IP、MAC地址等。 

(5)如果目标系统有显示设备,则初始化该类设备。 

(7)进去命令循环(即整个boot的工作循环),接受用户从串口输入的命令,然后进行相应的工作。

(6)初始化相关网络设备,填写IP、MAC地址等。 

}

2、kernel引导fs:

    1)获得可运行的Linux内核
    2)内核装载时的内存空间映射
    3)内核启始相关文件分析
    4)arch/i386/boot/bootsect.S
    5)arch/i386/boot/setup.S
    6)arch/i386/boot/compressed/head.S
    7)arch/i386/kernel/head.S
    8)start_kernel

    {

(7)进去命令循环(即整个boot的工作循环),接受用户从串口输入的命令,然后进行相应的工作。

在start_kernel()函数中:

}

2、kernel引导fs:

    1)获得可运行的Linux内核
    2)内核装载时的内存空间映射
    3)内核启始相关文件分析
    4)arch/i386/boot/bootsect.S
    5)arch/i386/boot/setup.S
    6)arch/i386/boot/compressed/head.S
    7)arch/i386/kernel/head.S
    8)start_kernel

    {

  输出Linux版本信息(printk(_banner))

在start_kernel()函数中:

  设置与体系结构相关的环境(setup_arch())

  输出Linux版本信息(printk(_banner))

  页表结构初始化(paging_init())

  设置与体系结构相关的环境(setup_arch())

  使用”arch/alpha/kernel/entry.S”中的入口点设置系统自陷入口(trap_init())

  页表结构初始化(paging_init())

  使用alpha_mv结构和entry.S入口初始化系统IRQ(init_IRQ())

  使用”arch/alpha/kernel/entry.S”中的入口点设置系统自陷入口(trap_init())

  核心进程调度器初始化(包括初始化几个缺省的Bottom-half,sched_init())

  使用alpha_mv结构和entry.S入口初始化系统IRQ(init_IRQ())

  时间、定时器初始化(包括读取CMOS时钟、估测主频、初始化定时器中断等,time_init())

  核心进程调度器初始化(包括初始化几个缺省的Bottom-half,sched_init())

  提取并分析核心启动参数(从环境变量中读取参数,设置相应标志位等待处理,(parse_options())

  时间、定时器初始化(包括读取CMOS时钟、估测主频、初始化定时器中断等,time_init())

  控制台初始化(为输出信息而先于PCI初始化,console_init())

  提取并分析核心启动参数(从环境变量中读取参数,设置相应标志位等待处理,(parse_options())

  剖析器数据结构初始化(prof_buffer和prof_len变量)

  控制台初始化(为输出信息而先于PCI初始化,console_init())

  核心Cache初始化(描述Cache信息的Cache,kmem_cache_init())

  剖析器数据结构初始化(prof_buffer和prof_len变量)

  延迟校准(获得时钟jiffies与CPU主频ticks的延迟,calibrate_delay())

  核心Cache初始化(描述Cache信息的Cache,kmem_cache_init())

  内存初始化(设置内存上下界和页表项初始值,mem_init())

  延迟校准(获得时钟jiffies与CPU主频ticks的延迟,calibrate_delay())

  创建和设置内部及通用cache(”slab_cache”,kmem_cache_sizes_init())

  内存初始化(设置内存上下界和页表项初始值,mem_init())

  创建uid taskcount SLAB cache(”uid_cache”,uidcache_init())

  创建和设置内部及通用cache(”slab_cache”,kmem_cache_sizes_init())

  创建文件cache(”files_cache”,filescache_init())

  创建uid taskcount SLAB cache(”uid_cache”,uidcache_init())

  创建目录cache(”dentry_cache”,dcache_init())

  创建文件cache(”files_cache”,filescache_init())

  创建与虚存相关的cache(”vm_area_struct”,”mm_struct”,vma_init())

  创建目录cache(”dentry_cache”,dcache_init())

  块设备读写缓冲区初始化(同时创建”buffer_head”cache用户加速访问,buffer_init())

  创建与虚存相关的cache(”vm_area_struct”,”mm_struct”,vma_init())

  创建页cache(内存页hash表初始化,page_cache_init())

  块设备读写缓冲区初始化(同时创建”buffer_head”cache用户加速访问,buffer_init())

  创建信号队列cache(”signal_queue”,signals_init())

  创建页cache(内存页hash表初始化,page_cache_init())

  初始化内存inode表(inode_init())

  创建信号队列cache(”signal_queue”,signals_init())

  创建内存文件描述符表(”filp_cache”,file_table_init())

  初始化内存inode表(inode_init())

  检查体系结构漏洞(对于alpha,此函数为空,check_bugs())

  创建内存文件描述符表(”filp_cache”,file_table_init())

  SMP机器其余CPU(除当前引导CPU)初始化(对于没有配置SMP的内核,此函数为空,smp_init())

  检查体系结构漏洞(对于alpha,此函数为空,check_bugs())

  启动init过程(run_init_process()
创建第一个核心线程,调用init()函数,原执行序列调用cpu_idle()
等待调度,init())

  SMP机器其余CPU(除当前引导CPU)初始化(对于没有配置SMP的内核,此函数为空,smp_init())

  至此start_kernel()结束,基本的核心环境已经建立起来了。

  启动init过程(run_init_process()
创建第一个核心线程,调用init()函数,原执行序列调用cpu_idle()
等待调度,init())

    }
    9)第一个内核线程 - kernel_init


三、start_kernel函数流程:

asmlinkage void __init start_kernel(void)
{
    char * command_line;
    extern const struct kernel_param __start___param[], __stop___param[];


    smp_setup_processor_id();//首先判断是否是SMP (对称多处理器)对单核SOC来说,mpidr = 0;


    /*
     * Need to run as early as possible, to initialize the
     * lockdep hash:
     */
    lockdep_init(); //只初始化该哈希表一次
    debug_objects_early_init();


    /*
     * Set up the the initial canary ASAP:
     */
    boot_init_stack_canary();//stack_canary的是带防止栈溢出攻击保护的堆栈


    /**
     * cgroup_init_early - cgroup initialization at system boot
     *
     * Initialize cgroups at system boot, and initialize any
     * subsystems that request early init.
     */
    cgroup_init_early(); 


    local_irq_disable();
    early_boot_irqs_disabled = true;


/*
 * Interrupts are still disabled. Do necessary setups, then
 * enable them
 */
    //初始化time ticket,时钟
    tick_init(); 


    //用以启动的CPU进行初始化。也就是初始化CPU0
    boot_cpu_init();


    //初始化页面
    page_address_init();


    printk(KERN_NOTICE "%s", linux_banner);


    //CPU架构相关的初始化
    setup_arch(&command_line);

    //初始化内存管理      
    mm_init_owner(&init_mm, &init_task);
    mm_init_cpumask(&init_mm);

    //处理启动命令行
    setup_command_line(command_line);


    //可能多余的初始化可能去判断cpu的最大支持个数
    setup_nr_cpu_ids();


    //为每个CPU开辟一块区域?
    setup_per_cpu_areas();


    //准备boot_cpu.如果是SMP环境,则设置boot CPU的一些数据。在引导过程中使用的CPU称为boot CPU
    smp_prepare_boot_cpu(); /* arch-specific boot-cpu hooks */


    //Linux将所有物理内存分为三个区,ZONE_DMA, ZONE_NORMAM, ZONE_HIGHMEM
    build_all_zonelists(NULL);

    //初始化page allocation相关结构
    page_alloc_init();


    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);
    /*
     * These use large bootmem allocations and must precede
     * kmem_cache_init()
     */
    setup_log_buf(0);


    //初始化process ID hash表
    pidhash_init();


    //文件系统caches预初始化
    vfs_caches_init_early();


    //初始化exception table
    sort_main_extable();


    //初始化trap,用以处理错误执行代码
    trap_init();

    //初始化内存管理
    mm_init();


    /*
     * Set up the scheduler prior starting any interrupts (such as the
     * timer interrupt). Full topology setup happens at smp_init()
     * time - but meanwhile we still have a functioning scheduler.
     */

    //进程调度初始化
    sched_init();
    /*
     * Disable preemption - early bootup scheduling is extremely
     * fragile until we cpu_idle() for the first time.
     */
    //  后当前进程将不能被强抢占
    preempt_disable();


    /*判断中断是否关闭,若打开则关闭中断*/    
    if (!irqs_disabled()) {
        printk(KERN_WARNING "start_kernel(): bug: interrupts were "
                "enabled *very* early, fixing it\n");
        local_irq_disable();
    }

    idr_init_cache();
    perf_event_init();

    //Read_Copy_Update机制初始 /*初始化互斥机制*/  
    rcu_init();
    radix_tree_init();

    /*中断向量的初始化*/  
    /* init some links before init_ISA_irqs() */
    early_irq_init();

    //初始化中断
    init_IRQ();
    prio_tree_init();


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


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


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


    //  初始化时钟源
    timekeeping_init();


    /*初始化系统时钟*/  
    time_init();


    /* 对内核的profile(一个内核性能调式工具)功能进行初始化 */    
    profile_init();

    call_function_init();//???
    if (!irqs_disabled())
        printk(KERN_CRIT "start_kernel(): bug: interrupts were "
                 "enabled early\n");
    early_boot_irqs_disabled = false;


     /*打开IRQ中断*/ 
    local_irq_enable();


    /* Interrupts are enabled now so all GFP allocations are safe. */
    gfp_allowed_mask = __GFP_BITS_MASK;


    //初始化CPU Cache
    kmem_cache_init_late();


    /*
     * HACK ALERT! This is early. We're enabling the console before
     * we've done PCI setups etc, and console_init() must be aware of
     * this. But we do want output early, in case something goes wrong.
     */
     
    //初始化console
    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 lock inversion 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();


    //页面分配debug启用
    enable_debug_pagealloc();
    debug_objects_mem_init();

    //memory leak 侦测初始化
    kmemleak_init();

    //设置每个CPU的页面集合
    setup_per_cpu_pageset();
    numa_policy_init();
    if (late_time_init)
        late_time_init();


    //初始化调度时钟
    sched_clock_init();


    /*校验延时函数的精确度*/  
    calibrate_delay();


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


    //anonymous page?什么意思?
    anon_vma_init();


#ifdef CONFIG_X86
    if (efi_enabled)
        efi_enter_virtual_mode();
#endif


    //初始化thread info
    thread_info_cache_init();


    //credential
    cred_init();

    //初始化fork
    fork_init(totalram_pages);

    //初始化/proc的cache?
    proc_caches_init();

    buffer_init();
    key_init();
    security_init();
    dbg_late_init();


    //文件系统cache初始化
    vfs_caches_init(totalram_pages);
    signals_init();

    /* rootfs populating might need page-writeback */
    page_writeback_init();


#ifdef CONFIG_PROC_FS
    proc_root_init();//本文件系统??
#endif


    cgroup_init();
    cpuset_init();
    taskstats_init_early();
    delayacct_init();


    check_bugs();


    acpi_early_init(); /* before LAPIC and SMP init */


    //simple firmware interface
    sfi_init_late();


    ftrace_init();


    /* Do the rest non-__init'ed, we're now alive */
    rest_init();
}

  至此start_kernel()结束,基本的核心环境已经建立起来了。

    }
    9)第一个内核线程 - kernel_init


三、start_kernel函数流程:

asmlinkage void __init start_kernel(void)
{
    char * command_line;
    extern const struct kernel_param __start___param[], __stop___param[];


    smp_setup_processor_id();//首先判断是否是SMP (对称多处理器)对单核SOC来说,mpidr = 0;


    /*
     * Need to run as early as possible, to initialize the
     * lockdep hash:
     */
    lockdep_init(); //只初始化该哈希表一次
    debug_objects_early_init();


    /*
     * Set up the the initial canary ASAP:
     */
    boot_init_stack_canary();//stack_canary的是带防止栈溢出攻击保护的堆栈


    /**
     * cgroup_init_early - cgroup initialization at system boot
     *
     * Initialize cgroups at system boot, and initialize any
     * subsystems that request early init.
     */
    cgroup_init_early(); 


    local_irq_disable();
    early_boot_irqs_disabled = true;


/*
 * Interrupts are still disabled. Do necessary setups, then
 * enable them
 */
    //初始化time ticket,时钟
    tick_init(); 


    //用以启动的CPU进行初始化。也就是初始化CPU0
    boot_cpu_init();


    //初始化页面
    page_address_init();


    printk(KERN_NOTICE "%s", linux_banner);


    //CPU架构相关的初始化
    setup_arch(&command_line);

    //初始化内存管理      
    mm_init_owner(&init_mm, &init_task);
    mm_init_cpumask(&init_mm);

    //处理启动命令行
    setup_command_line(command_line);


    //可能多余的初始化可能去判断cpu的最大支持个数
    setup_nr_cpu_ids();


    //为每个CPU开辟一块区域?
    setup_per_cpu_areas();


    //准备boot_cpu.如果是SMP环境,则设置boot CPU的一些数据。在引导过程中使用的CPU称为boot CPU
    smp_prepare_boot_cpu(); /* arch-specific boot-cpu hooks */


    //Linux将所有物理内存分为三个区,ZONE_DMA, ZONE_NORMAM, ZONE_HIGHMEM
    build_all_zonelists(NULL);

    //初始化page allocation相关结构
    page_alloc_init();


    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);
    /*
     * These use large bootmem allocations and must precede
     * kmem_cache_init()
     */
    setup_log_buf(0);


    //初始化process ID hash表
    pidhash_init();


    //文件系统caches预初始化
    vfs_caches_init_early();


    //初始化exception table
    sort_main_extable();


    //初始化trap,用以处理错误执行代码
    trap_init();

    //初始化内存管理
    mm_init();


    /*
     * Set up the scheduler prior starting any interrupts (such as the
     * timer interrupt). Full topology setup happens at smp_init()
     * time - but meanwhile we still have a functioning scheduler.
     */

    //进程调度初始化
    sched_init();
    /*
     * Disable preemption - early bootup scheduling is extremely
     * fragile until we cpu_idle() for the first time.
     */
    //  后当前进程将不能被强抢占
    preempt_disable();


    /*判断中断是否关闭,若打开则关闭中断*/    
    if (!irqs_disabled()) {
        printk(KERN_WARNING "start_kernel(): bug: interrupts were "
                "enabled *very* early, fixing it\n");
        local_irq_disable();
    }

    idr_init_cache();
    perf_event_init();

    //Read_Copy_Update机制初始 /*初始化互斥机制*/  
    rcu_init();
    radix_tree_init();

    /*中断向量的初始化*/  
    /* init some links before init_ISA_irqs() */
    early_irq_init();

    //初始化中断
    init_IRQ();
    prio_tree_init();


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


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


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


    //  初始化时钟源
    timekeeping_init();


    /*初始化系统时钟*/  
    time_init();


    /* 对内核的profile(一个内核性能调式工具)功能进行初始化 */    
    profile_init();

    call_function_init();//???
    if (!irqs_disabled())
        printk(KERN_CRIT "start_kernel(): bug: interrupts were "
                 "enabled early\n");
    early_boot_irqs_disabled = false;


     /*打开IRQ中断*/ 
    local_irq_enable();


    /* Interrupts are enabled now so all GFP allocations are safe. */
    gfp_allowed_mask = __GFP_BITS_MASK;


    //初始化CPU Cache
    kmem_cache_init_late();


    /*
     * HACK ALERT! This is early. We're enabling the console before
     * we've done PCI setups etc, and console_init() must be aware of
     * this. But we do want output early, in case something goes wrong.
     */
     
    //初始化console
    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 lock inversion 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();


    //页面分配debug启用
    enable_debug_pagealloc();
    debug_objects_mem_init();

    //memory leak 侦测初始化
    kmemleak_init();

    //设置每个CPU的页面集合
    setup_per_cpu_pageset();
    numa_policy_init();
    if (late_time_init)
        late_time_init();


    //初始化调度时钟
    sched_clock_init();


    /*校验延时函数的精确度*/  
    calibrate_delay();


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


    //anonymous page?什么意思?
    anon_vma_init();


#ifdef CONFIG_X86
    if (efi_enabled)
        efi_enter_virtual_mode();
#endif


    //初始化thread info
    thread_info_cache_init();


    //credential
    cred_init();

    //初始化fork
    fork_init(totalram_pages);

    //初始化/proc的cache?
    proc_caches_init();

    buffer_init();
    key_init();
    security_init();
    dbg_late_init();


    //文件系统cache初始化
    vfs_caches_init(totalram_pages);
    signals_init();

    /* rootfs populating might need page-writeback */
    page_writeback_init();


#ifdef CONFIG_PROC_FS
    proc_root_init();//本文件系统??
#endif


    cgroup_init();
    cpuset_init();
    taskstats_init_early();
    delayacct_init();


    check_bugs();


    acpi_early_init(); /* before LAPIC and SMP init */


    //simple firmware interface
    sfi_init_late();


    ftrace_init();


    /* Do the rest non-__init'ed, we're now alive */
    rest_init();
}

发表评论

电子邮件地址不会被公开。 必填项已用*标注