QEMU源码全解析29 —— QOM介绍(18)

88 篇文章 19 订阅
本文深入讲解QEMU中QOM(Quantum Object Model)的类属性设置及获取接口,以str类型的属性为例,探讨object_class_property_add_str函数及其内部使用的property_set_str和property_get_str函数。通过分析machine_class_init函数中的代码,展示如何在QEMU中实际操作类属性。
摘要由CSDN通过智能技术生成

接前一篇文章: QEMU源码全解析28 —— QOM介绍(17)

本文内容参考:

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

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

特此致谢!

前文讲解了类属性的添加接口。本文讲解类属性的设置及获取接口。

每一种类属性都有自己的add函数,如布尔(bool)、字符串(str)、enum(枚举)等。它们都在qom/object.c中,逐个来看:

  1. ObjectProperty *
  2. object_class_property_add_bool(ObjectClass *klass, const char *name,
  3. bool (*get)(Object *, Error **),
  4. void (*set)(Object *, bool, Error **))
  5. {
  6. BoolProperty *prop = g_malloc0(sizeof(*prop));
  7. prop->get = get;
  8. prop->set = set;
  9. return object_class_property_add(klass, name, "bool",
  10. get ? property_get_bool : NULL,
  11. set ? property_set_bool : NULL,
  12. NULL,
  13. prop);
  14. }
  1. ObjectProperty *
  2. object_class_property_add_enum(ObjectClass *klass, const char *name,
  3. const char *typename,
  4. const QEnumLookup *lookup,
  5. int (*get)(Object *, Error **),
  6. void (*set)(Object *, int, Error **))
  7. {
  8. EnumProperty *prop = g_malloc(sizeof(*prop));
  9. prop->lookup = lookup;
  10. prop->get = get;
  11. prop->set = set;
  12. return object_class_property_add(klass, name, typename,
  13. get ? property_get_enum : NULL,
  14. set ? property_set_enum : NULL,
  15. NULL,
  16. prop);
  17. }
  1. ObjectProperty *
  2. object_class_property_add_str(ObjectClass *klass, const char *name,
  3. char *(*get)(Object *, Error **),
  4. void (*set)(Object *, const char *,
  5. Error **))
  6. {
  7. StringProperty *prop = g_malloc0(sizeof(*prop));
  8. prop->get = get;
  9. prop->set = set;
  10. return object_class_property_add(klass, name, "string",
  11. get ? property_get_str : NULL,
  12. set ? property_set_str : NULL,
  13. NULL,
  14. prop);
  15. }

这次以str为例进行讲解。上一回已经讲过,类属性的添加是通过object_class_property_add接口完成的。而str类型属性的添加object_class_property_add_str函数则是调用了此接口。为了便于理解,再次贴出object_class_property_add函数代码,在qom/object.c中,如下:

  1. ObjectProperty *
  2. object_class_property_add(ObjectClass *klass,
  3. const char *name,
  4. const char *type,
  5. ObjectPropertyAccessor *get,
  6. ObjectPropertyAccessor *set,
  7. ObjectPropertyRelease *release,
  8. void *opaque)
  9. {
  10. ObjectProperty *prop;
  11. assert(!object_class_property_find(klass, name));
  12. prop = g_malloc0(sizeof(*prop));
  13. prop->name = g_strdup(name);
  14. prop->type = g_strdup(type);
  15. prop->get = get;
  16. prop->set = set;
  17. prop->release = release;
  18. prop->opaque = opaque;
  19. g_hash_table_insert(klass->properties, prop->name, prop);
  20. return prop;
  21. }

property_set_str和property_get_str函数在前文都已给出过,这里再贴一下,在同文件(qom/object.c)中:

  1. static void property_set_str(Object *obj, Visitor *v, const char *name,
  2. void *opaque, Error **errp)
  3. {
  4. StringProperty *prop = opaque;
  5. char *value;
  6. if (!visit_type_str(v, name, &value, errp)) {
  7. return;
  8. }
  9. prop->set(obj, value, errp);
  10. g_free(value);
  11. }
  1. static void property_get_str(Object *obj, Visitor *v, const char *name,
  2. void *opaque, Error **errp)
  3. {
  4. StringProperty *prop = opaque;
  5. char *value;
  6. Error *err = NULL;
  7. value = prop->get(obj, &err);
  8. if (err) {
  9. error_propagate(errp, err);
  10. return;
  11. }
  12. visit_type_str(v, name, &value, errp);
  13. g_free(value);
  14. }

从这两个函数中就可以看到,StringProperty结构的set和get成员函数为调用object_class_property_add_str函数时传入的参数,形参分别为:void (*set)(Object *, const char *, Error **))和char *(*get)(Object *, Error **)。在object_property_add_str函数中使用了上边的property_set_str和property_get_str函数。在property_set_str函数中最终调用了形参void (*set)(Object *, const char *, Error **)对应的实参,即真正类型属性的设置函数;在property_get_str函数中最终调用了形参char *(*get)(Object *, Error **)对应的实参,即真正的类型属性的获取函数。

仍以machine为例,hw/core/machine.c的machine_class_init函数代码如下:

  1. static void machine_class_init(ObjectClass *oc, void *data)
  2. {
  3. MachineClass *mc = MACHINE_CLASS(oc);
  4. /* Default 128 MB as guest ram size */
  5. mc->default_ram_size = 128 * MiB;
  6. mc->rom_file_has_mr = true;
  7. /* numa node memory size aligned on 8MB by default.
  8. * On Linux, each node's border has to be 8MB aligned
  9. */
  10. mc->numa_mem_align_shift = 23;
  11. object_class_property_add_str(oc, "kernel",
  12. machine_get_kernel, machine_set_kernel);
  13. object_class_property_set_description(oc, "kernel",
  14. "Linux kernel image file");
  15. object_class_property_add_str(oc, "initrd",
  16. machine_get_initrd, machine_set_initrd);
  17. object_class_property_set_description(oc, "initrd",
  18. "Linux initial ramdisk file");
  19. object_class_property_add_str(oc, "append",
  20. machine_get_append, machine_set_append);
  21. object_class_property_set_description(oc, "append",
  22. "Linux kernel command line");
  23. object_class_property_add_str(oc, "dtb",
  24. machine_get_dtb, machine_set_dtb);
  25. object_class_property_set_description(oc, "dtb",
  26. "Linux kernel device tree file");
  27. object_class_property_add_str(oc, "dumpdtb",
  28. machine_get_dumpdtb, machine_set_dumpdtb);
  29. object_class_property_set_description(oc, "dumpdtb",
  30. "Dump current dtb to a file and quit");
  31. object_class_property_add(oc, "boot", "BootConfiguration",
  32. machine_get_boot, machine_set_boot,
  33. NULL, NULL);
  34. object_class_property_set_description(oc, "boot",
  35. "Boot configuration");
  36. object_class_property_add(oc, "smp", "SMPConfiguration",
  37. machine_get_smp, machine_set_smp,
  38. NULL, NULL);
  39. object_class_property_set_description(oc, "smp",
  40. "CPU topology");
  41. object_class_property_add(oc, "phandle-start", "int",
  42. machine_get_phandle_start, machine_set_phandle_start,
  43. NULL, NULL);
  44. object_class_property_set_description(oc, "phandle-start",
  45. "The first phandle ID we may generate dynamically");
  46. object_class_property_add_str(oc, "dt-compatible",
  47. machine_get_dt_compatible, machine_set_dt_compatible);
  48. object_class_property_set_description(oc, "dt-compatible",
  49. "Overrides the \"compatible\" property of the dt root node");
  50. object_class_property_add_bool(oc, "dump-guest-core",
  51. machine_get_dump_guest_core, machine_set_dump_guest_core);
  52. object_class_property_set_description(oc, "dump-guest-core",
  53. "Include guest memory in a core dump");
  54. object_class_property_add_bool(oc, "mem-merge",
  55. machine_get_mem_merge, machine_set_mem_merge);
  56. object_class_property_set_description(oc, "mem-merge",
  57. "Enable/disable memory merge support");
  58. object_class_property_add_bool(oc, "usb",
  59. machine_get_usb, machine_set_usb);
  60. object_class_property_set_description(oc, "usb",
  61. "Set on/off to enable/disable usb");
  62. object_class_property_add_bool(oc, "graphics",
  63. machine_get_graphics, machine_set_graphics);
  64. object_class_property_set_description(oc, "graphics",
  65. "Set on/off to enable/disable graphics emulation");
  66. object_class_property_add_str(oc, "firmware",
  67. machine_get_firmware, machine_set_firmware);
  68. object_class_property_set_description(oc, "firmware",
  69. "Firmware image");
  70. object_class_property_add_bool(oc, "suppress-vmdesc",
  71. machine_get_suppress_vmdesc, machine_set_suppress_vmdesc);
  72. object_class_property_set_description(oc, "suppress-vmdesc",
  73. "Set on to disable self-describing migration");
  74. object_class_property_add_link(oc, "confidential-guest-support",
  75. TYPE_CONFIDENTIAL_GUEST_SUPPORT,
  76. offsetof(MachineState, cgs),
  77. machine_check_confidential_guest_support,
  78. OBJ_PROP_LINK_STRONG);
  79. object_class_property_set_description(oc, "confidential-guest-support",
  80. "Set confidential guest scheme to support");
  81. /* For compatibility */
  82. object_class_property_add_str(oc, "memory-encryption",
  83. machine_get_memory_encryption, machine_set_memory_encryption);
  84. object_class_property_set_description(oc, "memory-encryption",
  85. "Set memory encryption object to use");
  86. object_class_property_add_link(oc, "memory-backend", TYPE_MEMORY_BACKEND,
  87. offsetof(MachineState, memdev), object_property_allow_set_link,
  88. OBJ_PROP_LINK_STRONG);
  89. object_class_property_set_description(oc, "memory-backend",
  90. "Set RAM backend"
  91. "Valid value is ID of hostmem based backend");
  92. object_class_property_add(oc, "memory", "MemorySizeConfiguration",
  93. machine_get_mem, machine_set_mem,
  94. NULL, NULL);
  95. object_class_property_set_description(oc, "memory",
  96. "Memory size configuration");
  97. }

此函数中很多地方调用了object_class_property_add_str函数,以其中之一为例:

  1. object_class_property_add_str(oc, "kernel",
  2. machine_get_kernel, machine_set_kernel);

代码中的machine_set_kernel和machine_get_kernel函数就是传入object_class_property_add_str函数的与形参对应的实参,也即对于machine类的属性进行设置和获取时实际调用的函数。

至此, QEMU 中的QOM相关的内容就简要介绍完了。欲知后事如何,且看下回分解。

举报

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