网站cn和com有什么区别,做网站费用滁州,上蔡网站建设,wordpress怎么显示歌词接前一篇文章#xff1a;QEMU源码全解析13 —— QOM介绍#xff08;2#xff09; 本文内容参考#xff1a;
《趣谈Linux操作系统》 —— 刘超#xff0c;极客时间
《QEMU/KVM》源码解析与应用 —— 李强#xff0c;机械工业出版社
特此致谢#xff01; 上回书讲到了Q…接前一篇文章QEMU源码全解析13 —— QOM介绍2 本文内容参考
《趣谈Linux操作系统》 —— 刘超极客时间
《QEMU/KVM》源码解析与应用 —— 李强机械工业出版社
特此致谢 上回书讲到了QOM中第一部分——类型的注册讲了一半本文接着往下讲。
进入QEMU的main函数不久就以MODULE_INIT_QOM为参数调用了函数module_call_init也是上文书讲过的。那么具体是什么时候调用的module_call_init(MODULE_INIT_QOM)在QEMU源码qemu-7.1.07.1.0版本源码中搜索此关键字会有很多地方那么哪一个才是main函数不久后调用到的
QEMU源码全解析7 —— QEMU主函数中我曾经讲过main函数是在softmmu/main.c中为了便于理解和加深印象再次贴出源码
int qemu_main(int argc, char **argv, char **envp)
{int status;qemu_init(argc, argv, envp);status qemu_main_loop();qemu_cleanup();return status;
}#ifndef CONFIG_COCOA
int main(int argc, char **argv)
{return qemu_main(argc, argv, NULL);
}
#endif
主函数所在的位置是在softmmu目录下那么理论上应该从上述关键字搜索结果中找到同目录下的那个module_call_init(MODULE_INIT_QOM)它最有可能是我们要找的。在softmmu目录下的runstate.c中确实有一处调用代码如下
void qemu_init_subsystems(void)
{Error *err NULL;os_set_line_buffering();module_call_init(MODULE_INIT_TRACE);qemu_init_cpu_list();qemu_init_cpu_loop();qemu_mutex_lock_iothread();atexit(qemu_run_exit_notifiers);module_call_init(MODULE_INIT_QOM);module_call_init(MODULE_INIT_MIGRATION);runstate_init();precopy_infrastructure_init();postcopy_infrastructure_init();monitor_init_globals();if (qcrypto_init(err) 0) {error_reportf_err(err, cannot initialize crypto: );exit(1);}os_setup_early_signal_handling();bdrv_init_with_whitelist();socket_init();
}
是在qemu_init_subsystems函数中调用了module_call_init(MODULE_INIT_QOM);。而qemu_init_subsystems函数又是在qemu_init函数中被调用的代码片段如下softmmu/vl.c中
void qemu_init(int argc, char **argv, char **envp)
{QemuOpts *opts;QemuOpts *icount_opts NULL, *accel_opts NULL;QemuOptsList *olist;int optind;const char *optarg;MachineClass *machine_class;bool userconfig true;FILE *vmstate_dump_file NULL;qemu_add_opts(qemu_drive_opts);qemu_add_drive_opts(qemu_legacy_drive_opts);qemu_add_drive_opts(qemu_common_drive_opts);qemu_add_drive_opts(qemu_drive_opts);qemu_add_drive_opts(bdrv_runtime_opts);……qemu_init_subsystems();……}
这就很清楚了函数调用链为main() - qemu_main() - qemu_init() - qemu_init_subsystems() - module_call_init(MODULE_INIT_QOM)。
弄清楚这一点之后回到主题。为便于理解再贴一下module_call_init函数代码util/module.c中
void module_call_init(module_init_type type)
{ModuleTypeList *l;ModuleEntry *e;if (modules_init_done[type]) {return;}l find_type(type);QTAILQ_FOREACH(e, l, node) {e-init();}modules_init_done[type] true;
}
module_call_int函数执行了init_type_list[MODULE_INIT_QOM]链表上每一个ModuleEntry的init函数。
仍然以edu为例该类型的init函数是pci_edu_register_types前文中讲到的hw/misc/edu.c中的一句type_init(pci_edu_register_types)该函数在hw/misc/edu.c中代码如下
static void pci_edu_register_types(void)
{static InterfaceInfo interfaces[] {{ INTERFACE_CONVENTIONAL_PCI_DEVICE },{ },};static const TypeInfo edu_info {.name TYPE_PCI_EDU_DEVICE,.parent TYPE_PCI_DEVICE,.instance_size sizeof(EduState),.instance_init edu_instance_init,.class_init edu_class_init,.interfaces interfaces,};type_register_static(edu_info);
}
type_init(pci_edu_register_types)
pci_edu_register_types函数唯一的工作是构造了一个TypeInfo类型的edu_info并将其作为参数调用了type_register_static。
更多细节和分析请看下回。