从linux内核启动说起(一)

来源:互联网 发布:js动态添加css样式 编辑:程序博客网 时间:2024/04/29 13:21

Linux内核版本:

VERSION = 3 PATCHLEVEL = 0 SUBLEVEL = 53

Linux内核编译完成后会形成zImage内核文件,下载到开发板的处理器上面运行。

由Bootloader将内核镜像拷贝到ram中运行,通过call_linux(0, machine_type, kernel_params_base)。

其中,machine_tpye 是Bootloader检测出来的处理器类型, kernel_params_base 是启动参数在 RAM 的地址。通过这种方式将 Linux 启动需要的参数从 bootloader传递到内核。

对于ARM 系列处理器来说,zImage 的入口程序即为 arch/arm/boot/compressed/head.S。它依次完成以下工作:开启 MMU 和Cache,调用 decompress_kernel()解压内核,最后通过调用 call_kernel()进入非压缩内核 Image 的启动。

最重要的内核启动函数是start_kernel()//在init/main.c中定义的。

Start_kernel(),完成内核的启动。

主要完成一些硬件的初始化,一系列的与内核相关的初始化,调用用户的第一个进程“init”,并等待用户的进程执行,整个Linux内核启动完成。调用setup_arch()是其中的一个工作。

Setup_arch(),是与体系结构相关的函数,通过查找Linux下面arch目录下的文件我们会找到我们的bsp文件。那么就可以将我们的bsp文件的“去处”找到了。

掉过头来看一下bsp文件。以smdk-2440.c为例。

Bsp文件是为了创建一个machine_desc关于开发板的结构体,然后添加到.arch.info.init的段中,作为内核启动的初始化数据。machine_desc关于开发板的结构体然后到了setup_arch()中被“瓜分”,被赋值到相应的结构体中,在系统启动时,不同的函数调用。machine_desc关于开发板的结构体,创建过程参见代码。

 

MACHINE_START(S3C2440,"SMDK2440")

         /* Maintainer: Ben Dooks<ben-linux@fluff.org> */

         .boot_params         = S3C2410_SDRAM_PA + 0x100,

 

         .init_irq   = s3c24xx_init_irq,

         .map_io            =smdk2440_map_io,

         .init_machine = smdk2440_machine_init,

         .timer                =&s3c24xx_timer,

MACHINE_END

(在bsp文件中定义)

 

struct machine_desc {

       unsigned int             nr;         /* architecture number    */

       const char          *name;         /* architecture name */

       unsigned long          boot_params;    /* tagged list              */

       const char          **dt_compat;      /* array of device tree

                                           * 'compatible' strings     */

 

       unsigned int             nr_irqs; /* number of IRQs */

 

       unsigned int             video_start; /* start of video RAM       */

       unsigned int             video_end;  /* end of video RAM */

 

       unsigned int             reserve_lp0:1;   /* never has lp0  */

       unsigned int             reserve_lp1:1;   /* never has lp1  */

       unsigned int             reserve_lp2:1;   /* never has lp2  */

       unsigned int             soft_reboot:1;   /* soft reboot             */

       void                     (*fixup)(struct machine_desc *,

                                    struct tag *, char **,

                                    struct meminfo *);

       void                     (*reserve)(void);/*reserve mem blocks     */

       void                     (*map_io)(void);/*IO mapping function    */

       void                     (*init_early)(void);

       void                     (*init_irq)(void);

       struct sys_timer *timer;          /* system tick timer   */

       void                     (*init_machine)(void);

#ifdefCONFIG_MULTI_IRQ_HANDLER

       void                     (*handle_irq)(structpt_regs *);

#endif

};

 

#defineMACHINE_START(_type,_name)                   \

staticconst struct machine_desc __mach_desc_##_type      \

 __used                                                         \

 __attribute__((__section__(".arch.info.init")))= {        \

         .nr             =MACH_TYPE_##_type,               \

         .name               =_name,

#defineMACHINE_END                                   \

};

(在arch.h文件中定义)

 

Linux 内核对每种支持的开发板都会使用宏MACHINE_START,MACHINE_END来定义一个machine_desc结构。

Machine_desc存储与开发板相关的信息:开发板的机器类型号(mach_type),开发板的名称(machine_is_),其实io物理地址,内核启动参数的地址(.boot_params),中断初始化函数,io映射函数等。

原创粉丝点击