71v5 发表于 2014-06-26 15:05

freebsd9.2-创建elf文件格式对应的struct module对象

-处理name为"set_modmetadata_set"的section中保存的数据:/**********************************************************************
* typedef struct linker_file* linker_file_t;
   linker_file_t linker_kernel_file;

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

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

   函数linker_init_kernel_modules是一个简单的封装函数。
****************/
   366static void
   367linker_init_kernel_modules(void)
   368{
   369
   370          linker_file_register_modules(linker_kernel_file);
   371}

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

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

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

   355:调用函数module_register,该函数
**************************************/            
   348          first_error = 0;
   349          for (mdp = start; mdp < stop; mdp++) {
   350                  if ((*mdp)->md_type != MDT_MODULE)
   351                        continue;
   352                  moddata = (*mdp)->md_data;
   353                  KLD_DPF(FILE, ("Registering module %s in %s\n",
   354                      moddata->name, lf->filename));
   355                  error = module_register(moddata, lf);
   356                  if (error) {
   357                        printf("Module %s failed to register: %d\n",
   358                              moddata->name, error);
   359                        if (first_error == 0)
   360                                  first_error = error;
   361                  }
   362          }
   363          return (first_error);
   364}[在看module_register函数之前,先熟悉一点数据结构]:/******************************************************************************
* link:
   链接到modules链表中
   struct {                                                               
       struct module *tqe_next;/* next element */                     
       struct module **tqe_prev; /* address of previous next element */
       TRACEBUF                                                      
   }link;

   flink:
   链接到struct linker_file对象的modules成员中
   struct {                                                               
       struct module *tqe_next;/* next element */                     
       struct module **tqe_prev; /* address of previous next element */
       TRACEBUF                                                      
   }flink;
   
   file:包含该module的linker file

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

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

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

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

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

   参数描述:
   data:&elf32_mod。
   container:linker_kernel_file。
*********************************/
   151        int
   152        module_register(const moduledata_t *data, linker_file_t container)
   153        {
   154                size_t namelen;
   155                module_t newmod;
   156       
/*************************************************************************************
* 158-164:
   函数module_lookupbyname在modules链表中查找name为"elf32"的module,
   如果已经存在,就返回一个错误码。

   165-170:
   执行到这里的话,就表示要创建一个name为"elf32"的module,此时分配
   一个大小为sizeof(struct module) + namelen的内存空间,用来保存描述
   该module的struct mopdule对象和module的name。

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

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

   178:将elf32_module链接到modules链表中。
   180-181:根据情况将elf32_module链接到struct linker_file对象的modules链表中。
*****************************************************/
   157                MOD_XLOCK;
   158                newmod = module_lookupbyname(data->name);
   159                if (newmod != NULL) {
   160                        MOD_XUNLOCK;
   161                        printf("module_register: module %s already exists!\n",
   162                          data->name);
   163                        return (EEXIST);
   164                }
   165                namelen = strlen(data->name) + 1;
   166                newmod = malloc(sizeof(struct module) + namelen, M_MODULE, M_WAITOK);
   167                if (newmod == NULL) {
   168                        MOD_XUNLOCK;
   169                        return (ENOMEM);
   170                }
   171                newmod->refs = 1;
   172                newmod->id = nextid++;
   173                newmod->name = (char *)(newmod + 1);
   174                strcpy(newmod->name, data->name);
   175                newmod->handler = data->evhand ? data->evhand : modevent_nop;
   176                newmod->arg = data->priv;
   177                bzero(&newmod->data, sizeof(newmod->data));
   178                TAILQ_INSERT_TAIL(&modules, newmod, link);
   179       
   180                if (container)
   181                        TAILQ_INSERT_TAIL(&container->modules, newmod, flink);
   182                newmod->file = container;
   183                MOD_XUNLOCK;
   184                return (0);
   185        }
页: [1]
查看完整版本: freebsd9.2-创建elf文件格式对应的struct module对象