加载中…
个人资料
散人
散人
  • 博客等级:
  • 博客积分:0
  • 博客访问:15,610
  • 关注人气:4
  • 获赠金笔:0支
  • 赠出金笔:0支
  • 荣誉徽章:
相关博文
推荐博文
谁看过这篇博文
加载中…
正文 字体大小:

2.4 linux ld连接脚本探索

(2011-01-05 10:58:40)

 

jiffies = jiffies_64;

SECTIONS

{

    . = DRAM_VIRTUAL_BASE;

    dram_start = .;

#ifdef CONFIG_ETRAX_ARCH_V10

    ibr_start = .;

#else

    ebp_start = .;

   

   

    .boot : { *(.boot) }

#endif

   

    . = DRAM_VIRTUAL_BASE + 0x4000;

 

    _text = .;         

    text_start = .;        

    _stext = .;

    __stext = .;

    .text : {

        TEXT_TEXT

        SCHED_TEXT

        LOCK_TEXT

        *(.fixup)

        *(.text.__*)

    }

 

    _etext = . ;           

    __etext = .;

    . = ALIGN(4);          

    __start___ex_table = .;

    __ex_table : { *(__ex_table) }

    __stop___ex_table = .;

 

    RODATA

    . = ALIGN (4);

    ___data_start = . ;

    __Sdata = . ;

    .data : {          

        DATA_DATA

    }

    __edata = . ;          

    _edata = . ;

 

    . = ALIGN(PAGE_SIZE);  

    .data.init_task : { *(.data.init_task) }

 

    . = ALIGN(PAGE_SIZE);      

    __init_begin = .;

    .init.text : {   //__init字段相对应

           _sinittext = .; // 全局的变量

           INIT_TEXT

           _einittext = .;

    }

    .init.data : { INIT_DATA }

    . = ALIGN(16);

    __setup_start = .;// 命令行参数的早期处理 在void __init parse_early_param(void)处调用

    .init.setup : { *(.init.setup) }

    __setup_end = .;

#ifdef CONFIG_ETRAX_ARCH_V32

__start___param = .;// 启动参数段 在asmlinkage void __init start_kernel(void)static void __init param_sysfs_builtin(void) 处被调用

    __param : { *(__param) }

    __stop___param = .;

#endif

    .initcall.init : {               

            // __devinit/pure_initcall/device_initcall/fs_initcall/arch_initcall/core_initcall对应

        __initcall_start = .; // static void __init do_pre_smp_initcalls(void)这边被初始化

        INITCALLS

        __initcall_end = .;

    }

    .con_initcall.init : {

        __con_initcall_start = .;// 控制台初始化代码段 void __init console_init(void) 处被调用

        *(.con_initcall.init)

        __con_initcall_end = .;

    }

    SECURITY_INIT

#ifdef CONFIG_ETRAX_ARCH_V10

#ifdef CONFIG_BLK_DEV_INITRD

广告:

补充一下与rootfs相关的一些知识,Initrdboot loader initialized RAM disklinux内核启动前, boot loader 会将存储介质中的 initrd 文件加载到内存,内核启动时会在访问真正的根文件系统前先访问该内存中的 initrd 文件系统。在 boot loader 配置了 initrd 的情况下,内核启动被分成了两个阶段,第一阶段先执行 initrd 文件系统中的"某个文件",完成加载驱动模块等任务,第二阶段才会执行真正的根文件系统中的 /sbin/init 进程,Linux2.6 内核对 Initrd 的处理流程

cpio-initrd 的处理流程:

1boot loader 把内核以及 initrd 文件加载到内存的特定位置。

2.内核判断initrd的文件格式,如果是cpio格式。

3.将initrd的内容释放到rootfs中。

4.执行initrd中的/init文件,执行到这一点,内核的工作全部结束,完全交给/init文件处理。

image-initrd的处理流程

1boot loader把内核以及initrd文件加载到内存的特定位置。

2.内核判断initrd的文件格式,如果不是cpio格式,将其作为image-initrd处理。

3.内核将initrd的内容保存在rootfs下的/initrd.image文件中。

4.内核将/initrd.image的内容读入/dev/ram0设备中,也就是读入了一个内存盘中。

5.接着内核以可读写的方式把/dev/ram0设备挂载为原始的根文件系统。

6.如果/dev/ram0被指定为真正的根文件系统,那么内核跳至最后一步正常启动。

7.执行initrd上的/linuxrc文件,linuxrc通常是一个脚本文件,负责加载内核访问根文件系统必须的驱动,以及加载根文件系统。

8/linuxrc执行完毕,常规根文件系统被挂载

9.如果常规根文件系统存在/initrd目录,那么/dev/ram0将从/移动到/initrd。否则如果/initrd目录不存在, /dev/ram0将被卸载。

10.在常规根文件系统上进行正常启动过程 ,执行/sbin/init

通过上面的流程介绍可知,Linux2.6内核对image-initrd的处理流程同linux2.4内核相比并没有显著的变化, cpio-initrd的处理流程相比于image-initrd的处理流程却有很大的区别,流程非常简单,在后面的源代码分析中,读者更能体会到处理的简捷。

现在看一下rootfs的初始化几挂载流程:

  static int init(void * unused){
[1]      populate_rootfs();//populate_rootfs函数负责加载initramfscpio-initrd

                             下面的代码段.init.ramfs就是在这边被初始调用的
[2]      if (sys_access((const char __user *) "/init", 0) == 0)
                 execute_command = "/init";//如果rootfs的根目录下中包含/init进程,则赋予
         else                              //execute_command,init函数的末尾会被

                 prepare_namespace();     //执行。否则执行prepare_namespace函数,initrd//在该函数中被加载的
[3]      if (sys_open((const char __user *) "/dev/console", O_RDWR, 0) < 0)
                 printk(KERN_WARNING "Warning: unable to open an initial console.\n");
                                            //将控制台设置为标准输入输出
         (void) sys_dup(0);
         (void) sys_dup(0);

[4]      if (execute_command) //如果rootfs中存在init进程,将后续的处理工作交给该//init进程。
                 run_init_process(execute_command); //cpio-initrd里面没init进程
         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.");

    .init.ramfs : {//用户空间的守护进程是在init函数里面实现的,


         __initramfs_start = .;
         *(.init.ramfs)            
         __initramfs_end = .;      

                                 

    }

#endif

#endif

    __vmlinux_end = .;     

#ifdef CONFIG_ETRAX_ARCH_V32

    PERCPU(PAGE_SIZE)

 

    .init.ramfs : {

        __initramfs_start = .;

        *(.init.ramfs)

        __initramfs_end = .;

    }

#endif

   

    . = ALIGN(PAGE_SIZE);

    __init_end = .;

 

    __data_end = . ;       

    __bss_start = .;       

    .bss : {

        *(COMMON)

        *(.bss)

    }

    . =  ALIGN (0x20);

    _end = .;

    __end = .;

 

   

    /DISCARD/ : {

        EXIT_TEXT

        EXIT_DATA

        *(.exitcall.exit)

        }

    dram_end = dram_start + (CONFIG_ETRAX_DRAM_SIZE - __CONFIG_ETRAX_VMEM_SIZE)*1024*1024;

0

阅读 评论 收藏 转载 喜欢 打印举报/Report
  • 评论加载中,请稍候...
发评论

    发评论

    以上网友发言只代表其个人观点,不代表新浪网的观点或立场。

      

    新浪BLOG意见反馈留言板 欢迎批评指正

    新浪简介 | About Sina | 广告服务 | 联系我们 | 招聘信息 | 网站律师 | SINA English | 会员注册 | 产品答疑

    新浪公司 版权所有