QEMU源码全解析3 —— QEMU参数解析(3)

接前一篇文章: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等结构之间的关系,且看下回分解。

猜你喜欢

转载自blog.csdn.net/phmatthaus/article/details/131547841