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

接前一篇文章:QEMU源码全解析5 —— QEMU参数解析(5)

本文内容参考:

《趣谈Linux操作系统》 —— 刘超,极客时间

《QEMU/KVM》源码解析与应用 —— 李强,机械工业出版社

特此致谢!

上一回说到了qemu_opts_parse_noisily函数只是简单调用了opt_parse函数,opt_parse函数解析出一个QemuOpts。本文对opt_parse函数进行详解。

为了便于理解,先再贴一下qemu_opts_parse_noisily函数代码,在util/qemu-option.c中,代码如下:

/**
 * Create a QemuOpts in @list and with options parsed from @params.
 * If @permit_abbrev, the first key=value in @params may omit key=,
 * and is treated as if key was @list->implied_opt_name.
 * Report errors with error_report_err().  This is inappropriate in
 * QMP context.  Do not use this function there!
 * Return the new QemuOpts on success, null pointer on error.
 */
QemuOpts *qemu_opts_parse_noisily(QemuOptsList *list, const char *params,
                                  bool permit_abbrev)
{
    Error *err = NULL;
    QemuOpts *opts;
    bool help_wanted = false;
 
    opts = opts_parse(list, params, permit_abbrev, true,
                      opts_accepts_any(list) ? NULL : &help_wanted,
                      &err);
    if (!opts) {
        assert(!!err + !!help_wanted == 1);
        if (help_wanted) {
            qemu_opts_print_help(list, true);
        } else {
            error_report_err(err);
        }
    }
    return opts;
}

opts_parse函数在util/qemu-option.c中,代码如下:

static QemuOpts *opts_parse(QemuOptsList *list, const char *params,
                            bool permit_abbrev,
                            bool warn_on_flag, bool *help_wanted, Error **errp)
{
    const char *firstname;
    char *id = opts_parse_id(params);
    QemuOpts *opts;

    assert(!permit_abbrev || list->implied_opt_name);
    firstname = permit_abbrev ? list->implied_opt_name : NULL;

    opts = qemu_opts_create(list, id, !list->merge_lists, errp);
    g_free(id);
    if (opts == NULL) {
        return NULL;
    }

    if (!opts_do_parse(opts, params, firstname,
                       warn_on_flag, help_wanted, errp)) {
        qemu_opts_del(opts);
        return NULL;
    }

    return opts;
}

opts_parse函数调用的最重要的两个函数是qemu_opts_create和opts_do_parse。一个一个来看。

qemu_opts_create函数在util/qemu-option.c中,代码如下:

QemuOpts *qemu_opts_create(QemuOptsList *list, const char *id,
                           int fail_if_exists, Error **errp)
{
    QemuOpts *opts = NULL;

    if (list->merge_lists) {
        if (id) {
            error_setg(errp, QERR_INVALID_PARAMETER, "id");
            return NULL;
        }
        opts = qemu_opts_find(list, NULL);
        if (opts) {
            return opts;
        }
    } else if (id) {
        assert(fail_if_exists);
        if (!id_wellformed(id)) {
            error_setg(errp, QERR_INVALID_PARAMETER_VALUE, "id",
                       "an identifier");
            error_append_hint(errp, "Identifiers consist of letters, digits, "
                              "'-', '.', '_', starting with a letter.\n");
            return NULL;
        }
        opts = qemu_opts_find(list, id);
        if (opts != NULL) {
            error_setg(errp, "Duplicate ID '%s' for %s", id, list->name);
            return NULL;
        }
    }
    opts = g_malloc0(sizeof(*opts));
    opts->id = g_strdup(id);
    opts->list = list;
    loc_save(&opts->loc);
    QTAILQ_INIT(&opts->head);
    QTAILQ_INSERT_TAIL(&list->head, opts, next);
    return opts;
}

qemu_opts_create用来创建opts并将其插入到QemuOptsList上。

opts_do_parse函数同样在util/qemu-option.c中,代码如下:

static bool opts_do_parse(QemuOpts *opts, const char *params,
                          const char *firstname,
                          bool warn_on_flag, bool *help_wanted, Error **errp)
{
    char *option, *value;
    const char *p;
    QemuOpt *opt;

    for (p = params; *p;) {
        p = get_opt_name_value(p, firstname, warn_on_flag, help_wanted, &option, &value);
        if (help_wanted && *help_wanted) {
            g_free(option);
            g_free(value);
            return false;
        }
        firstname = NULL;

        if (!strcmp(option, "id")) {
            g_free(option);
            g_free(value);
            continue;
        }

        opt = opt_create(opts, option, value);
        g_free(option);
        if (!opt_validate(opt, errp)) {
            qemu_opt_del(opt);
            return false;
        }
    }

    return true;
}

opts_do_parse函数的作用就是就是开始解析出一个一个的QemuOpt,解析出参数的值。QEMU的参数可以有多种情况,例如:foo,bar中foo表示开启一个flag;而另一种形式为foo=bar。对于这种情况,opts_do_parse需要处理各种可能的情况,并对每个值生成一个QemuOpt。下边以这个例子具体说明。

opts_do_parse函数首先根据各种情况(foo,bar或者foo=bar,more)解析出option以及value;然后调用opt_create,在该函数中会分配一个QemuOpt结构并进行初始化。

你可能感兴趣的:(KVM,QEMU,QEMU,KVM)