免费注册 查看新帖 |

Chinaunix

  平台 论坛 博客 文库
最近访问板块 发新帖
查看: 2409 | 回复: 0
打印 上一主题 下一主题

[FreeBSD] freebsd9.2-创建elf文件格式对应的struct module对象 [复制链接]

论坛徽章:
0
跳转到指定楼层
1 [收藏(0)] [报告]
发表于 2014-06-26 15:05 |只看该作者 |倒序浏览
[linker_init_kernel_modules函数]-处理name为"set_modmetadata_set"的section中保存的数据:
  1. /**********************************************************************
  2. * typedef struct linker_file* linker_file_t;
  3.    linker_file_t linker_kernel_file;

  4.    对于内核本身,在初始化阶段,会创建一个struct linker_file类型
  5.    的数据对象来描述内核本身。全局变量linker_kernel_file指向描述内核
  6.    本身的struct linker_file对象。

  7.    当使用kldload系统调用加载一个模块时,内核也会为该模块创建
  8.    一个struct linker_file类型的数据对象来描述该模块。

  9.    函数linker_init_kernel_modules是一个简单的封装函数。
  10. ****************/
  11.    366  static void
  12.    367  linker_init_kernel_modules(void)
  13.    368  {
  14.    369  
  15.    370          linker_file_register_modules(linker_kernel_file);
  16.    371  }

  17.    325  static int
  18.    326  linker_file_register_modules(linker_file_t lf)
  19.    327  {
  20.    328          struct mod_metadata **start, **stop, **mdp;
  21.    329          const moduledata_t *moddata;
  22.    330          int first_error, error;
  23.    331  
  24.    332          KLD_DPF(FILE, ("linker_file_register_modules: registering modules"
  25.    333              " in %s\n", lf->filename));
  26.    334  
  27. /*****************************************************************************************
  28. * 335-347:
  29.    确定name为"set_modmetadata_set"的section的起始地址和结尾地址,起始地址和结尾地址
  30.    分别通过变量start和stop返回。
  31. *   
  32. *************************************/
  33.    335          if (linker_file_lookup_set(lf, "modmetadata_set", &start,
  34.    336              &stop, NULL) != 0) {
  35.    337                  /*
  36.    338                   * This fallback should be unnecessary, but if we get booted
  37.    339                   * from boot2 instead of loader and we are missing our
  38.    340                   * metadata then we have to try the best we can.
  39.    341                   */
  40.    342                  if (lf == linker_kernel_file) {
  41.    343                          start = SET_BEGIN(modmetadata_set);
  42.    344                          stop = SET_LIMIT(modmetadata_set);
  43.    345                  } else
  44.    346                          return (0);
  45.    347          }
  46. /****************************************************************************************
  47. * 349-362:依次处理name为"set_modmetadata_set"的section的数据,这里的数据就是类型为
  48.             struct mod_metadata的数据对象的地址,并且只处理类型为MDT_MODULE的
  49.             struct mod_metadata的数据对象。

  50.    这里以一个实例来简要分析一下,看看module_register函数到底做了什么工作:
  51.    static struct mod_metadata _mod_metadata_md_elf32 = {       
  52.        MDT_STRUCT_VERSION,//md_version成员                                       
  53.        MDT_MODULE, //md_type成员               
  54.        &elf32_mod, //md_data成员                               
  55.        "elf32"           //md_cval成员                                               
  56.    };       

  57.    352:moddata此时的值就为&elf32_mod。

  58.    355:调用函数module_register,该函数
  59. **************************************/            
  60.    348          first_error = 0;
  61.    349          for (mdp = start; mdp < stop; mdp++) {
  62.    350                  if ((*mdp)->md_type != MDT_MODULE)
  63.    351                          continue;
  64.    352                  moddata = (*mdp)->md_data;
  65.    353                  KLD_DPF(FILE, ("Registering module %s in %s\n",
  66.    354                      moddata->name, lf->filename));
  67.    355                  error = module_register(moddata, lf);
  68.    356                  if (error) {
  69.    357                          printf("Module %s failed to register: %d\n",
  70.    358                              moddata->name, error);
  71.    359                          if (first_error == 0)
  72.    360                                  first_error = error;
  73.    361                  }
  74.    362          }
  75.    363          return (first_error);
  76.    364  }
复制代码
[在看module_register函数之前,先熟悉一点数据结构]:
  1. /******************************************************************************
  2. * link:
  3.    链接到modules链表中
  4.    struct {                                                               
  5.        struct module *tqe_next;  /* next element */                     
  6.        struct module **tqe_prev; /* address of previous next element */  
  7.        TRACEBUF                                                        
  8.    }link;

  9.    flink:
  10.    链接到struct linker_file对象的modules成员中
  11.    struct {                                                               
  12.        struct module *tqe_next;  /* next element */                     
  13.        struct module **tqe_prev; /* address of previous next element */  
  14.        TRACEBUF                                                        
  15.    }flink;
  16.    
  17.    file:包含该module的linker file

  18.    refs:引用计数器。
  19.    
  20.    name: module的名字,一般为struct moduledata对象的name成员,
  21.          module_lookupbyname函数使用.

  22.    id:module的唯一标识符,从1开始分配,module_lookupbyid函数使用.

  23.    handler:相应module的处理函数,一般为struct moduledata对象的evhand成员.

  24.    arg:handler所需的参数,一般为struct moduledata对象的priv成员.

  25. * data:moduel指定的数据 .
  26. ***************************/      
  27.     49  struct module {
  28.     50          TAILQ_ENTRY(module)     link;   /* chain together all modules */   
  29.     51          TAILQ_ENTRY(module)     flink;  /* all modules in a file */
  30.     52          struct linker_file      *file;  /* file which contains this module */
  31.     53          int                     refs;   /* reference count */
  32.     54          int                     id;     /* unique id number */
  33.     55          char                    *name;  /* module name */
  34.     56          modeventhand_t          handler;        /* event handler */
  35.     57          void                    *arg;   /* argument for handler */
  36.     58          modspecific_t           data;   /* module specific data */
  37.     59  };
复制代码
[变量modules]-modules链接了注册到内核的全部struct module数据对象:
  1. static TAILQ_HEAD(modulelist, module) modules;
  2. struct modulelist {                                                           
  3.    struct module *tqh_first;                     
  4.    struct module **tqh_last;        
  5.    TRACEBUF                                                        
  6. }modules;
复制代码
[函数module_register]:
  1. /*********************************************************************
  2. * static moduledata_t elf32_mod = {
  3.          "elf32", //name成员
  4.          elf32_modevent,//evhand成员
  5.          (void *)&elf32_execsw //priv成员
  6.    };

  7.    参数描述:
  8.    data:&elf32_mod。
  9.    container:linker_kernel_file。
  10. *********************************/
  11.    151        int
  12.    152        module_register(const moduledata_t *data, linker_file_t container)
  13.    153        {
  14.    154                size_t namelen;
  15.    155                module_t newmod;
  16.    156       
  17. /*************************************************************************************
  18. * 158-164:
  19.    函数module_lookupbyname在modules链表中查找name为"elf32"的module,
  20.    如果已经存在,就返回一个错误码。
  21.   
  22.    165-170:
  23.    执行到这里的话,就表示要创建一个name为"elf32"的module,此时分配
  24.    一个大小为sizeof(struct module) + namelen的内存空间,用来保存描述
  25.    该module的struct mopdule对象和module的name。

  26.    这里将name为"elf32"的module对应的struct module对象简记为elf32_module。

  27.    171-177:初始化相关的成员。
  28.    static int nextid = 1;
  29.    175:elf32_module的handler成员设置为elf32_modevent函数的地址。
  30.    176:elf32_module的arg成员设置为&elf32_execsw。

  31.    178:将elf32_module链接到modules链表中。
  32.    180-181:根据情况将elf32_module链接到struct linker_file对象的modules链表中。
  33. *****************************************************/
  34.    157                MOD_XLOCK;
  35.    158                newmod = module_lookupbyname(data->name);
  36.    159                if (newmod != NULL) {
  37.    160                        MOD_XUNLOCK;
  38.    161                        printf("module_register: module %s already exists!\n",
  39.    162                            data->name);
  40.    163                        return (EEXIST);
  41.    164                }
  42.    165                namelen = strlen(data->name) + 1;
  43.    166                newmod = malloc(sizeof(struct module) + namelen, M_MODULE, M_WAITOK);
  44.    167                if (newmod == NULL) {
  45.    168                        MOD_XUNLOCK;
  46.    169                        return (ENOMEM);
  47.    170                }
  48.    171                newmod->refs = 1;
  49.    172                newmod->id = nextid++;
  50.    173                newmod->name = (char *)(newmod + 1);
  51.    174                strcpy(newmod->name, data->name);
  52.    175                newmod->handler = data->evhand ? data->evhand : modevent_nop;
  53.    176                newmod->arg = data->priv;
  54.    177                bzero(&newmod->data, sizeof(newmod->data));
  55.    178                TAILQ_INSERT_TAIL(&modules, newmod, link);
  56.    179       
  57.    180                if (container)
  58.    181                        TAILQ_INSERT_TAIL(&container->modules, newmod, flink);
  59.    182                newmod->file = container;
  60.    183                MOD_XUNLOCK;
  61.    184                return (0);
  62.    185        }
复制代码
您需要登录后才可以回帖 登录 | 注册

本版积分规则 发表回复

  

北京盛拓优讯信息技术有限公司. 版权所有 京ICP备16024965号-6 北京市公安局海淀分局网监中心备案编号:11010802020122 niuxiaotong@pcpop.com 17352615567
未成年举报专区
中国互联网协会会员  联系我们:huangweiwei@itpub.net
感谢所有关心和支持过ChinaUnix的朋友们 转载本站内容请注明原作者名及出处

清除 Cookies - ChinaUnix - Archiver - WAP - TOP