Linux开发心得总结17 - Linux程序数据段分布分析

linux内核空间分布解析
SECTIONS
{
 . = TEXTADDR;   /* 表示内核编译后链接的首地址,由arch/arm/makefile编译选项指定,如果是armv版本,则一般指定为0xc0008000,这是linux内核起来后,mmu起作用时的内核空间地址,这个值跟具体的处理器体系有关,需要额外指定的.*/
 .init : {   /* Init code and data  */
  _stext = .;  /* 段名称,在c函数中可以通过此名称来访问这段存储器上的变量,此段名称被head_armv.s文件引用,用于记录起始程序段的地址。*/
  __init_begin = .; /* 初始化代码和数据的开始名称,c函数可以通过此名称来访问其中的变量*/
   *(.text.init) /* 用于初始化的代码段,一般是指定head_armv.s和其他*.s文件到这里,在c语言中以"__init"作为前缀的函数也将被摆放在这个区间中,然后在kernel启动时,按照摆放的先后顺序依次执行一次。*/
  __proc_info_begin = .; /* 此处存放的是此kernel所支持的处理器列表c函数可以通过此名称来访问其中的变量,以便获得处理器信息,在setup_processor()函数中调用。*/
   *(.proc.info) /* 此列表一般在arch/arm/mm/proc-arm926.S文件中指定变量内容,具体内容见后面的结构体介绍,在嵌入式系统中,一般此处只有一个结构体。*/
  __proc_info_end = .; /* 处理器列表结构体结束标志,可以通过c函数访问此变量*/
  __arch_info_begin = .; /* 架构信息开始结构体变量,可以通过c函数访问此结构体,在setup_machine()函数中调用*/
   *(.arch.info) /* 汇编文件中没有使用,而是在mach/arch.h文件中使用,用于定义MACHINE_START这个宏的属性,此宏定义了machine_desc结构体的初始化信息,此结构体的具体信息参加下面的描述。*/
  __arch_info_end = .; /* 架构信息结束变量*/
  __tagtable_begin = .; /* tag表开始变量,在setup.c文件的parse_tag()函数中调用,具体结构体参数列表如下面所述*/
   *(.taglist) /* c文件中所有含有__tag前缀的结构体将存储器这个区域中。主要是setup.c文件中定义了若干处理tag的函数,用于分析linux启动参数,这个已经是老的启动参数传递和处理模式了。tag号是一组宏,固定了每个tag的意义。*/
  __tagtable_end = .; /* tag表结束变量*/
   *(.data.init) /* 初始化的数据区,c文件中所有表示“__initdata”前缀的数据都将存储在这个地方,例如default_command_line等数组都是存储在这个地方的。*/
  . = ALIGN(16);
  __setup_start = .; /* 此变量在init/main.c文件中被使用,主要用来处理commandline变量的*/
   *(.setup.init) /* c函数中所有含有"__initsetup"前缀的函数将都存储在这个区域中*/
  __setup_end = .; /* 这个区域是为了保持对老版本的兼容,在新版本中,此结构体已经基本不再使用了,即处理commandline的函数由上面的其他函数替代了。*/
  __initcall_start = .; /* 此变量在init/main.c文件中被使用,主要是在初始进程init起来后作一些基础设备配置时调用的,do_basic_setup()此函数调用do_initcalls()实现对此区域中的函数的调用。*/
   *(.initcall.init)/* c函数中所有含有"__init_cal"前缀的函数都将被摆放在这个区域中。*/
  __initcall_end = .; /* 在现在的kernel中,这个部分的init函数也基本没有了。*/
  . = ALIGN(4096); /* 页对齐*/
  __init_end = .;  /* 初始函数和数据结束。*/
 }

 /DISCARD/ : {   /* Exit code and data  */
  *(.text.exit)  /* c函数中所有含有"__exit"前缀的函数都存放在这个区域,当函数退出或者系统关机时将自动被调用,在driver程序中被广泛使用*/
  *(.data.exit)  /* c函数中所有含有"__exitdata"前缀的数据都摆放爱这个区域。系统中很少使用这个区域存放信息。*/
  *(.exitcall.exit) /* c函数中所有含有"__exit_call"前缀的数据都摆放爱这个区域。系统中很少使用这个区域存放此类函数。*/
 }

 .text : {   /* Real text segment  */
  _text = .;  /* Text and read-only data */
   *(.text) /* 所有其他普通代码都放在此区域*/
   *(.fixup) /* 驱动和.s文件中定义的一些fixup类型的函数*/
   *(.gnu.warning) /* gnu的warning信息*/
   *(.rodata) /* read-only 数据*/
   *(.rodata.*) /* 所有其他read-only数据*/
   *(.glue_7) /* */
   *(.glue_7t)
  *(.got)   /* Global offset table  */

  _etext = .;  /* End of text section  */
 }

 .kstrtab : { *(.kstrtab) } /* kstrtab类型的函数放置在此区域,主要是在insmod.c函数中注册驱动时使用的.*/
     /* Kernel string table*/
 . = ALIGN(16);
 __ex_table : {   /* Exception table  */
  __start___ex_table = .; /* 异常处理函数组开始变量*/
   *(__ex_table)
  __stop___ex_table = .; /* 异常处理函数组结束变量*/
 }

 __ksymtab : {   /* Kernel symbol table  */
  __start___ksymtab = .; /* 内核符号表开始变量*/
   *(__ksymtab)
  __stop___ksymtab = .; /* 内核符号表结束变量*/
 }

 . = ALIGN(8192);

 .data : {   /* 数据段*/
  /*
   * first, the init task union, aligned
   * to an 8192 byte boundary.
   */
  *(.init.task)  /* 进程初始化时的一些数据常数和全局变量*/

  /*
   * then the cacheline aligned data
   */
  . = ALIGN(32); 
  *(.data.cacheline_aligned) /* cacheline对齐相关的数据常数和全局变量*/

  /*
   * and the usual data section
   */ 
  *(.data)  /* 普通数据常数和全局变量*/
  CONSTRUCTORS

  _edata = .;
 }

 .bss : {   /* 变量段*/
  __bss_start = .; /* BSS 变量段开始标志  */
  *(.bss)   /* 普通变量段*/
  *(COMMON)  /* common段*/
  _end = . ;  /* 此处一般就是代码段的结尾了.*/
 }
     /* Stabs debugging sections. */
 .stab 0 : { *(.stab) }
 .stabstr 0 : { *(.stabstr) }
 .stab.excl 0 : { *(.stab.excl) }
 .stab.exclstr 0 : { *(.stab.exclstr) }
 .stab.index 0 : { *(.stab.index) }
 .stab.indexstr 0 : { *(.stab.indexstr) }
 .comment 0 : { *(.comment) }
}
 kernel所支持的处理器信息结构体如下:
 struct proc_info_list {
  unsigned int  cpu_val;  /* 处理器特征值*/
  unsigned int  cpu_mask;  /* 处理器特征值掩码*/
  unsigned long  __cpu_mmu_flags; /* used by head-armv.S */
  unsigned long  __cpu_flush;  /* used by head-armv.S */
  const char  *arch_name;  /* 处理器体系名称变量地址*/
  const char  *elf_name;  /* elf名称变量地址*/
  unsigned int  elf_hwcap;  /* elf标志字*/
  struct proc_info_item *info;   /* 处理器结构信息变量地址,包括处理器名称,体系等可以供人阅读的信息*/
  struct processor *proc;   /* 处理器函数变量地址,此处定义了一组用汇编编写的处理此体系处理器的底层函数列表*/
 };
 此结构体一般是在arch/arm/mm/proc-arm926.S中固定赋值。即编译时支持哪个体系的处理器结构,就会在列表中指名此值。

 struct machine_desc {
  /*
   * Note! The first four elements are used
   * by assembler code in head-armv.S
   */
  unsigned int  nr;  /* architecture number 架构号,在mach-types.h中统一定义的*/
  unsigned int  phys_ram; /* start of physical ram 物理存储器开始地址*/
  unsigned int  phys_io; /* start of physical io  物理io空间开始地址*/
  unsigned int  io_pg_offst; /* byte offset for io  io空间页表入口地址的偏移量
        * page tabe entry */

  const char  *name;  /* architecture name 架构名称数组地址*/
  unsigned int  param_offset; /* parameter page 参数页地址偏移量*/

  unsigned int  video_start; /* start of video RAM 视频缓冲区RAM的开始地址*/
  unsigned int  video_end; /* end of video RAM 视频缓冲区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 param_struct *, char **,
       struct meminfo *);  /* fixup函数实现的地址*/
  void   (*map_io)(void);/* IO mapping function iomap函数,在mm中实现*/
  void   (*init_irq)(void); /* 初始化irq函数地址,在irq.c文件中实现*/ 
 };
 此结构体是通过MACHINE_START这一组宏来初始化的,一般是在\arch\arm\mach-fv13xx\arch.c文件中实现。

 struct tagtable {
  u32 tag;    /* tag号*/
  int (*parse)(const struct tag *); /* tag分析处理函数*/
 };
  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值