接前一篇文章:QEMU源码全解析6 —— QEMU参数解析(6)
本文内容参考:
《趣谈Linux操作系统》 —— 刘超,极客时间
《QEMU/KVM》源码解析与应用 —— 李强,机械工业出版社
特此致谢!
本系列前几篇文章一直在围绕QEMU参数解析进行讲解,本篇文章开始我们换一个角度研究,从QEMU主函数作为入口进行深入。
前边文章提到QEMU的主函数是softmmu/vl.c中的qemu_init(),实际上并不是,而是真正有main函数的。老版本的main函数位于softmmu/vl.c中;而在较新的版本(笔者的版本是qemu-7.1.0)中,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
可以看到,main函数中只是简单调用了qemu_main函数,将实际的工作交给了它,即真正的QEMU主函数实际上是qemu_main()。
qemu_main()中一共包括三大函数:qemu_init、qemu_mail_loop、qemu_cleanup。之所以说是大函数,是因为虽然看似简单,但其里边包含的代码和内容多了去了。
接下来看一下qemu_init函数中的一句module_call_init(MODULE_INIT_QDOM)。为了便于理解,把qemu_init函数的代码片段在此贴出:
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_add_opts(&qemu_chardev_opts);
qemu_add_opts(&qemu_device_opts);
qemu_add_opts(&qemu_netdev_opts);
qemu_add_opts(&qemu_nic_opts);
qemu_add_opts(&qemu_net_opts);
qemu_add_opts(&qemu_rtc_opts);
qemu_add_opts(&qemu_global_opts);
qemu_add_opts(&qemu_mon_opts);
qemu_add_opts(&qemu_trace_opts);
qemu_plugin_add_opts();
qemu_add_opts(&qemu_option_rom_opts);
qemu_add_opts(&qemu_accel_opts);
qemu_add_opts(&qemu_mem_opts);
qemu_add_opts(&qemu_smp_opts);
qemu_add_opts(&qemu_boot_opts);
qemu_add_opts(&qemu_add_fd_opts);
qemu_add_opts(&qemu_object_opts);
qemu_add_opts(&qemu_tpmdev_opts);
qemu_add_opts(&qemu_overcommit_opts);
qemu_add_opts(&qemu_msg_opts);
qemu_add_opts(&qemu_name_opts);
qemu_add_opts(&qemu_numa_opts);
qemu_add_opts(&qemu_icount_opts);
qemu_add_opts(&qemu_semihosting_config_opts);
qemu_add_opts(&qemu_fw_cfg_opts);
qemu_add_opts(&qemu_action_opts);
module_call_init(MODULE_INIT_OPTS);
……
}
顾名思义,module_call_init(MODULE_INIT_OPTS)函数的作用是初始化所有的Module,这是非常关键的一步,因此我放在了主函数之后第一个要讲解的位置。不过本回只是起个头,预知此函数详情,请看下回。