接前一篇文章: QEMU源码全解析2 —— QEMU参数解析(2)
本文内容参考:
《趣谈 Linux 操作系统》 —— 刘超, 极客时间
《 QEMU /KVM》源码解析与应用 —— 李强,机械工业出版社
特此致谢!
上回说到QEMUOptions结构以及全局变量qemu_options,本节继续对其进行深入探究。
为便于理解和会议,在此再贴出QEMUOption结构的代码,在softmmu/vl.c中:
- typedef struct QEMUOption {
- const char *name;
- int flags;
- int index;
- uint32_t arch_mask;
- } QEMUOption;
QEMUOption提供了参数的基本信息情况。实际参数的保存是由3个数据结构完成的。
QEMU将所有参数分成了几个大选项,也可以叫类,如-enable- kvm 和- kernel 都属于machine相关的,每个大选项使用struct QemuOptsList结构体表示,其定义在include/qemu/option.h中,代码如下:
- struct QemuOptsList {
- const char *name;
- const char *implied_opt_name;
- bool merge_lists; /* Merge multiple uses of option into a single list? */
- QTAILQ_HEAD(, QemuOpts) head;
- QemuOptDesc desc[];
- };
QEMU在util/qemu-config.c中定义了struct QemuOptsList类型的全局变量vm_config_groups,代码如下:
- static QemuOptsList *vm_config_groups[48];
- static QemuOptsList *drive_config_groups[5];
这表示可以支持48个大选项。在main函数(softmmu/vl.c的qemu_init函数)中用qemu_add_opts将各个OemuOptsList添加到vm_config_groups中。
终于回到了本系列第一篇文章中就给出的代码,在softmmu/vl.c中的void qemu_init(int argc, char **argv)中:
- 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);
是时候来看一下qemu_add_opts的实现了,在util/qemu-config.c中,代码如下:
- void qemu_add_opts(QemuOptsList *list)
- {
- int entries, i;
-
- entries = ARRAY_SIZE(vm_config_groups);
- entries--; /* keep list NULL terminated */
- for (i = 0; i < entries; i++) {
- if (vm_config_groups[i] == NULL) {
- vm_config_groups[i] = list;
- return;
- }
- }
- fprintf(stderr, "ran out of space in vm_config_groups");
- abort();
- }
该函数实现了如上所述的功能:qemu_add_opts将各个OemuOptsList添加到vm_config_groups(static QemuOptsList *vm_config_groups[48])中。
每个QemuOptsList存储了大选项支持的所有小选项,比如-overcommit大选项定义如下(softmmu/vl.c中):
- static QemuOptsList qemu_overcommit_opts = {
- .name = "overcommit",
- .head = QTAILQ_HEAD_INITIALIZER(qemu_overcommit_opts.head),
- .desc = {
- {
- .name = "mem-lock",
- .type = QEMU_OPT_BOOL,
- },
- {
- .name = "cpu-pm",
- .type = QEMU_OPT_BOOL,
- },
- { /* end of list */ }
- },
- };
-overcommit只支持两个值为bool(QEMU_OPT_BOOL)的子选项,即只能有-overcommit mem-lock=on/off和-overcommit cpu-pm=on/off。
但是有些大选项就并不是这样了,比如-device这个(种)选项就没有这么死板了。-device大选项定义如下(同样在oftmmu/vl.c中):
- QemuOptsList qemu_device_opts = {
- .name = "device",
- .implied_opt_name = "driver",
- .head = QTAILQ_HEAD_INITIALIZER(qemu_device_opts.head),
- .desc = {
- /*
- * no elements => accept any
- * sanity checking will happen later
- * when setting device properties
- */
- { /* end of list */ }
- },
- };
-device并没有规定必需的选项,因为设备有无数多种,不可能全部进行规定,解析就是按照“,”或者“=”来进行的。每个子选项由一个QemuOpt结构表示。
关于QemuOpt结构的具体定义以及QemuOptsList、QemuOpt、QemuOpts等结构之间的关系,且看下回分解。