本文主要是介绍【QEMU系统分析之实例篇(十五)】,希望对大家解决编程问题提供一定的参考价值,需要的开发者们随着小编来一起学习吧!
系列文章目录
第十五章 QEMU系统仿真的机器创建分析实例
文章目录
- 系列文章目录
- 第十五章 QEMU系统仿真的机器创建分析实例
- 前言
- 一、QEMU是什么?
- 二、QEMU系统仿真的机器创建分析实例
- 1.系统仿真的命令行参数
- 2.应用旧的机器设置项
- qemu_apply_legacy_machine_options()
- keyval_dashify();
- 移除与机器状态属性无关的旧配置项
- 3.调试输出
- 总结
前言
本文以 QEMU 8.2.2 为例,分析其作为系统仿真工具的工作过程,并为读者展示各种 QEMU 系统仿真的启动配置实例。
本文读者需要具备一定的 QEMU 系统仿真使用经验,并对 C 语言编程有一定了解。
一、QEMU是什么?
QEMU 是一个通用且开源的机器模拟器和虚拟机。
其官方主页是:https://www.qemu.org/
二、QEMU系统仿真的机器创建分析实例
1.系统仿真的命令行参数
QEMU 作为系统仿真工具,其入口代码在 system/main.c 文件中,初始化函数 qemu_init() 的实现在 system/vl.c 文件中。
前文完成创建目标机器的过程分析,本文将继续后续运行过程的分析,读者需要对 QEMU 系统启动过程的程序代码有所了解,相关内容可以参考《QEMU系统分析之启动篇》系列文章。
..\qemu\8.2.2-qkd\qemu-system-x86_64.exe -cpu "Penryn" -M "q35,accel=whpx,smm=off" -m "6G" -display "sdl" -audio "sdl,model=hda" -vga "std" -L "data"
2.应用旧的机器设置项
这部分代码在 system/vl.c 文件中,实现如下:
int qemu_init(int argc, char **argv)
{
...qemu_apply_legacy_machine_options(machine_opts_dict);
...
}
前文分析了创建后端驱动过程中控制台和字符设备的创建过程,本文继续完成块设备和音频设备驱动的创建过程。
qemu_apply_legacy_machine_options()
函数 qemu_apply_legacy_machine_options() 代码如下:
static void qemu_apply_legacy_machine_options(QDict *qdict)
{const char *value;QObject *prop;keyval_dashify(qdict, &error_fatal);/* Legacy options do not correspond to MachineState properties. */value = qdict_get_try_str(qdict, "accel");if (value) {accelerators = g_strdup(value);qdict_del(qdict, "accel");}value = qdict_get_try_str(qdict, "igd-passthru");if (value) {object_register_sugar_prop(ACCEL_CLASS_NAME("xen"), "igd-passthru", value,false);qdict_del(qdict, "igd-passthru");}value = qdict_get_try_str(qdict, "kvm-shadow-mem");if (value) {object_register_sugar_prop(ACCEL_CLASS_NAME("kvm"), "kvm-shadow-mem", value,false);qdict_del(qdict, "kvm-shadow-mem");}value = qdict_get_try_str(qdict, "kernel-irqchip");if (value) {object_register_sugar_prop(ACCEL_CLASS_NAME("kvm"), "kernel-irqchip", value,false);object_register_sugar_prop(ACCEL_CLASS_NAME("whpx"), "kernel-irqchip", value,false);qdict_del(qdict, "kernel-irqchip");}value = qdict_get_try_str(qdict, "memory-backend");if (value) {if (mem_path) {error_report("'-mem-path' can't be used together with""'-machine memory-backend'");exit(EXIT_FAILURE);}/* Resolved later. */ram_memdev_id = g_strdup(value);qdict_del(qdict, "memory-backend");}prop = qdict_get(qdict, "memory");if (prop) {have_custom_ram_size =qobject_type(prop) == QTYPE_QDICT &&qdict_haskey(qobject_to(QDict, prop), "size");}
}
首先对关键字和值做连字符处理。
keyval_dashify();
代码如下:
/* *Non*recursively replace underscores with dashes in QDict keys. */
static void keyval_dashify(QDict *qdict, Error **errp)
{const QDictEntry *ent, *next;char *p;for (ent = qdict_first(qdict); ent; ent = next) {g_autofree char *new_key = NULL;next = qdict_next(qdict, ent);if (!strchr(ent->key, '_')) {continue;}new_key = g_strdup(ent->key);for (p = new_key; *p; p++) {if (*p == '_') {*p = '-';}}if (qdict_haskey(qdict, new_key)) {error_setg(errp, "Conflict between '%s' and '%s'", ent->key, new_key);return;}qobject_ref(ent->value);qdict_put_obj(qdict, new_key, ent->value);qdict_del(qdict, ent->key);}
}
如果做连字符处理后关键字有冲突,则出错返回。
移除与机器状态属性无关的旧配置项
代码如下:
static void qemu_apply_legacy_machine_options(QDict *qdict)
{
.../* Legacy options do not correspond to MachineState properties. */value = qdict_get_try_str(qdict, "accel");if (value) {accelerators = g_strdup(value);qdict_del(qdict, "accel");}value = qdict_get_try_str(qdict, "igd-passthru");if (value) {object_register_sugar_prop(ACCEL_CLASS_NAME("xen"), "igd-passthru", value,false);qdict_del(qdict, "igd-passthru");}value = qdict_get_try_str(qdict, "kvm-shadow-mem");if (value) {object_register_sugar_prop(ACCEL_CLASS_NAME("kvm"), "kvm-shadow-mem", value,false);qdict_del(qdict, "kvm-shadow-mem");}value = qdict_get_try_str(qdict, "kernel-irqchip");if (value) {object_register_sugar_prop(ACCEL_CLASS_NAME("kvm"), "kernel-irqchip", value,false);object_register_sugar_prop(ACCEL_CLASS_NAME("whpx"), "kernel-irqchip", value,false);qdict_del(qdict, "kernel-irqchip");}value = qdict_get_try_str(qdict, "memory-backend");if (value) {if (mem_path) {error_report("'-mem-path' can't be used together with""'-machine memory-backend'");exit(EXIT_FAILURE);}/* Resolved later. */ram_memdev_id = g_strdup(value);qdict_del(qdict, "memory-backend");}prop = qdict_get(qdict, "memory");if (prop) {have_custom_ram_size =qobject_type(prop) == QTYPE_QDICT &&qdict_haskey(qobject_to(QDict, prop), "size");}
}
3.调试输出
首先,添加跟踪调试信息,修改后的代码如下:
static void qemu_create_early_backends(void)
{...huedbg_flag = 1;HUEDBG("\n");huedbg_dump_device_configs(2);HUEDBG("\n");qemu_create_early_backends();HUEDBG("\n");huedbg_dump_device_configs(2);HUEDBG("\n");huedbg_flag = 0;...
}
运行后,输出信息如下:
总结
以上分析了系统初始化过程中应用旧的机器设置项的过程。
这篇关于【QEMU系统分析之实例篇(十五)】的文章就介绍到这儿,希望我们推荐的文章对编程师们有所帮助!