目录
- qemu源码解析【05】qemu启动初始化流程
-
- [1. qemu入口函数](#1. qemu入口函数)
- [2. qemu_init()函数内容](#2. qemu_init()函数内容)
-
- [2.1 构建参数链表](#2.1 构建参数链表)
- [2.2 一些系统相关的交互](#2.2 一些系统相关的交互)
- [2.3 解析启动的命令行参数](#2.3 解析启动的命令行参数)
qemu源码解析【05】qemu启动初始化流程
1. qemu入口函数
-
qemu入口main函数位于system/main.c文件,main函数内容很简单,完成启动前的初始化,进入主循环
int qemu_default_main(void)
{
int status;status = qemu_main_loop(); qemu_cleanup(status); return status;
}
int (*qemu_main)(void) = qemu_default_main;
int main(int argc, char **argv)
{
// 初始化流程
qemu_init(argc, argv);
// 主循环函数
return qemu_main();
} -
这篇文章浅浅研究一下qemu_init(),也就是初始化函数里面的代码
2. qemu_init()函数内容
- 下面开始逐段分析qemu_init()函数内容
2.1 构建参数链表
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_fw_cfg_opts);
qemu_add_opts(&qemu_action_opts);
qemu_add_run_with_opts();
module_call_init(MODULE_INIT_OPTS);
- 在util/qemu-config.c中有2个全局的QemuOptsList*数组,vm_config_groups[48]和drive_config_groups[5]
- 以上代码就是在初始化这2个数组,将qemu_drive_opts,qemu_device_opts这些结构体填到这2个数组中,这里面存的其实就是qemu启动时我们传进去的那些参数,或者我们没有指定这些一些参数,系统帮我们给定了一个默认值
- 然后还有个module_call_init()函数,作用跟上一章的qom链表初始化过程差不多,就是根据init_type_list[MODULE_INIT_OPTS]链表上挂的所有成员,挨个初始化
2.2 一些系统相关的交互
// 初始化glib的日志库
error_init(argv[0]);
// 找到当前执行的文件路径,存在静态变量exec_dir中
qemu_init_exec_dir(argv[0]);
// 保存当前机器的一些架构信息
os_setup_limits();
qemu_init_arch_modules();
// 初始化子系统,例如上文说到的那个QOM链表
qemu_init_subsystems();
2.3 解析启动的命令行参数
-
qemu自带了一个字典库,位于qobject/qdict.c文件中
-
解析命令行参数之前,先创建了一个字典库,用来保存所有解析结果
-
这段解析参数很多,但逻辑很简单,就是机械地解析所有参数,然后保存到字典中,以下做了删除
-
可以看到,我们传入的cpu,hda,smp等所有的参数都在此处完成和解析和保存
machine_opts_dict = qdict_new(); if (userconfig) { qemu_read_default_config_file(&error_fatal); } /* second pass of option parsing */ optind = 1; for(;;) { if (optind >= argc) break; if (argv[optind][0] != '-') { loc_set_cmdline(argv, optind, 1); drive_add(IF_DEFAULT, 0, argv[optind++], HD_OPTS); } else { const QEMUOption *popt; popt = lookup_opt(argc, argv, &optarg, &optind); if (!(popt->arch_mask & arch_type)) { error_report("Option not supported for this target"); exit(1); } switch(popt->index) { case QEMU_OPTION_cpu: /* hw initialization will check this */ cpu_option = optarg; break; case QEMU_OPTION_hda: case QEMU_OPTION_hdb: case QEMU_OPTION_hdc: case QEMU_OPTION_hdd: drive_add(IF_DEFAULT, popt->index - QEMU_OPTION_hda, optarg, HD_OPTS); break; // 此处省略 // ....... default: error_report("Option not supported in this build"); exit(1); } } }