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

88 篇文章 19 订阅
本文详细解析QEMU参数解析的关键函数opt_parse,通过分析qemu_opts_create和opts_do_parse,阐述如何创建QemuOptsList并从命令行参数中提取选项和值。代码示例来自util/qemu-option.c。
摘要由CSDN通过智能技术生成

接前一篇文章: 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中,代码如下:

  1. /**
  2. * Create a QemuOpts in @list and with options parsed from @params.
  3. * If @permit_abbrev, the first key=value in @params may omit key=,
  4. * and is treated as if key was @list->implied_opt_name.
  5. * Report errors with error_report_err(). This is inappropriate in
  6. * QMP context. Do not use this function there!
  7. * Return the new QemuOpts on success, null pointer on error.
  8. */
  9. QemuOpts *qemu_opts_parse_noisily(QemuOptsList *list, const char *params,
  10. bool permit_abbrev)
  11. {
  12. Error *err = NULL;
  13. QemuOpts *opts;
  14. bool help_wanted = false;
  15. opts = opts_parse(list, params, permit_abbrev, true,
  16. opts_accepts_any(list) ? NULL : &help_wanted,
  17. &err);
  18. if (!opts) {
  19. assert(!!err + !!help_wanted == 1);
  20. if (help_wanted) {
  21. qemu_opts_print_help(list, true);
  22. } else {
  23. error_report_err(err);
  24. }
  25. }
  26. return opts;
  27. }

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

  1. static QemuOpts *opts_parse(QemuOptsList *list, const char *params,
  2. bool permit_abbrev,
  3. bool warn_on_flag, bool *help_wanted, Error **errp)
  4. {
  5. const char *firstname;
  6. char *id = opts_parse_id(params);
  7. QemuOpts *opts;
  8. assert(!permit_abbrev || list->implied_opt_name);
  9. firstname = permit_abbrev ? list->implied_opt_name : NULL;
  10. opts = qemu_opts_create(list, id, !list->merge_lists, errp);
  11. g_free(id);
  12. if (opts == NULL) {
  13. return NULL;
  14. }
  15. if (!opts_do_parse(opts, params, firstname,
  16. warn_on_flag, help_wanted, errp)) {
  17. qemu_opts_del(opts);
  18. return NULL;
  19. }
  20. return opts;
  21. }

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

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

  1. QemuOpts *qemu_opts_create(QemuOptsList *list, const char *id,
  2. int fail_if_exists, Error **errp)
  3. {
  4. QemuOpts *opts = NULL;
  5. if (list->merge_lists) {
  6. if (id) {
  7. error_setg(errp, QERR_INVALID_PARAMETER, "id");
  8. return NULL;
  9. }
  10. opts = qemu_opts_find(list, NULL);
  11. if (opts) {
  12. return opts;
  13. }
  14. } else if (id) {
  15. assert(fail_if_exists);
  16. if (!id_wellformed(id)) {
  17. error_setg(errp, QERR_INVALID_PARAMETER_VALUE, "id",
  18. "an identifier");
  19. error_append_hint(errp, "Identifiers consist of letters, digits, "
  20. "'-', '.', '_', starting with a letter.\n");
  21. return NULL;
  22. }
  23. opts = qemu_opts_find(list, id);
  24. if (opts != NULL) {
  25. error_setg(errp, "Duplicate ID '%s' for %s", id, list->name);
  26. return NULL;
  27. }
  28. }
  29. opts = g_malloc0(sizeof(*opts));
  30. opts->id = g_strdup(id);
  31. opts->list = list;
  32. loc_save(&opts->loc);
  33. QTAILQ_INIT(&opts->head);
  34. QTAILQ_INSERT_TAIL(&list->head, opts, next);
  35. return opts;
  36. }

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

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

  1. static bool opts_do_parse(QemuOpts *opts, const char *params,
  2. const char *firstname,
  3. bool warn_on_flag, bool *help_wanted, Error **errp)
  4. {
  5. char *option, *value;
  6. const char *p;
  7. QemuOpt *opt;
  8. for (p = params; *p;) {
  9. p = get_opt_name_value(p, firstname, warn_on_flag, help_wanted, &option, &value);
  10. if (help_wanted && *help_wanted) {
  11. g_free(option);
  12. g_free(value);
  13. return false;
  14. }
  15. firstname = NULL;
  16. if (!strcmp(option, "id")) {
  17. g_free(option);
  18. g_free(value);
  19. continue;
  20. }
  21. opt = opt_create(opts, option, value);
  22. g_free(option);
  23. if (!opt_validate(opt, errp)) {
  24. qemu_opt_del(opt);
  25. return false;
  26. }
  27. }
  28. return true;
  29. }

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结构并进行初始化。

举报

选择你想要举报的内容(必选)
  • 内容涉黄
  • 政治相关
  • 内容抄袭
  • 涉嫌广告
  • 内容侵权
  • 侮辱谩骂
  • 样式问题
  • 其他