- 论坛徽章:
- 0
|
[linker_init_kernel_modules函数]-处理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是一个简单的封装函数。
- ****************/
- 366 static void
- 367 linker_init_kernel_modules(void)
- 368 {
- 369
- 370 linker_file_register_modules(linker_kernel_file);
- 371 }
- 325 static int
- 326 linker_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指定的数据 .
- ***************************/
- 49 struct 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 }
复制代码 |
|