QEMU源码全解析26 —— QOM介绍(15)

88 篇文章 19 订阅
本文深入解析QEMU源码中QOM(对象查询机制)的对象属性设置过程,通过`object_property_set`函数及不同类型的set函数,如`property_set_bool`,阐述对象属性如何被设置。以`machine`对象为例,展示`machine_set_machine`函数在属性设置中的作用。
摘要由CSDN通过智能技术生成

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

本文内容参考:

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

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

特此致谢!

前文讲解了对象属性的添加接口。本文讲解对象属性的设置接口。

对象属性的设置是通过object_property_set函数来完成的。该函数同样在qom/object.c中,代码如下:

  1. bool object_property_set(Object *obj, const char *name, Visitor *v,
  2. Error **errp)
  3. {
  4. ERRP_GUARD();
  5. ObjectProperty *prop = object_property_find_err(obj, name, errp);
  6. if (prop == NULL) {
  7. return false;
  8. }
  9. if (!prop->set) {
  10. error_setg(errp, QERR_PERMISSION_DENIED);
  11. return false;
  12. }
  13. prop->set(obj, v, name, prop->opaque, errp);
  14. return !*errp;
  15. }

其实object_property_set函数只是简单地调用了ObjectProperty的set函数。

每一种属性类型都有自己的set函数,如布尔(bool)、字符串(str)、enum(枚举)等。它们都在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_set_enum(Object *obj, Visitor *v, const char *name,
  2. void *opaque, Error **errp)
  3. {
  4. EnumProperty *prop = opaque;
  5. int value;
  6. if (!visit_type_enum(v, name, &value, prop->lookup, errp)) {
  7. return;
  8. }
  9. prop->set(obj, value, errp);
  10. }
  1. static void property_set_bool(Object *obj, Visitor *v, const char *name,
  2. void *opaque, Error **errp)
  3. {
  4. BoolProperty *prop = opaque;
  5. bool value;
  6. if (!visit_type_bool(v, name, &value, errp)) {
  7. return;
  8. }
  9. prop->set(obj, value, errp);
  10. }

以bool为例进行讲解。可以看到,property_set_bool函数调用了具体属性(BoolProperty)的set函数,这是在创建这个属性的时候指定的。上一回已经讲过,对象属性的添加是通过object_property_add接口完成的。而bool类型对象属性的添加object_property_add_bool函数则是调用了此接口。object_property_add_bool函数在qom/object.c中,代码如下:

  1. ObjectProperty *
  2. object_property_add_bool(Object *obj, 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_property_add(obj, name, "bool",
  10. get ? property_get_bool : NULL,
  11. set ? property_set_bool : NULL,
  12. property_release_data,
  13. prop);
  14. }

从这个函数中就可以看到,BoolProperty结构的set成员函数为调用object_property_add_bool函数时传入的参数,形参为:void (*set)(Object *, bool, Error **)。在object_property_add_bool函数中使用了上边的property_set_bool函数,在property_set_bool函数中最终调用了形参void (*set)(Object *, bool, Error **)对应的实参,即真正对象属性的设置函数。

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

  1. static void machine_initfn(Object *obj)
  2. {
  3. MachineState *ms = MACHINE(obj);
  4. MachineClass *mc = MACHINE_GET_CLASS(obj);
  5. container_get(obj, "/peripheral");
  6. container_get(obj, "/peripheral-anon");
  7. ms->dump_guest_core = true;
  8. ms->mem_merge = true;
  9. ms->enable_graphics = true;
  10. ms->kernel_cmdline = g_strdup("");
  11. ms->ram_size = mc->default_ram_size;
  12. ms->maxram_size = mc->default_ram_size;
  13. if (mc->nvdimm_supported) {
  14. Object *obj = OBJECT(ms);
  15. ms->nvdimms_state = g_new0(NVDIMMState, 1);
  16. object_property_add_bool(obj, "nvdimm",
  17. machine_get_nvdimm, machine_set_nvdimm);
  18. object_property_set_description(obj, "nvdimm",
  19. "Set on/off to enable/disable "
  20. "NVDIMM instantiation");
  21. object_property_add_str(obj, "nvdimm-persistence",
  22. machine_get_nvdimm_persistence,
  23. machine_set_nvdimm_persistence);
  24. object_property_set_description(obj, "nvdimm-persistence",
  25. "Set NVDIMM persistence"
  26. "Valid values are cpu, mem-ctrl");
  27. }
  28. if (mc->cpu_index_to_instance_props && mc->get_default_cpu_node_id) {
  29. ms->numa_state = g_new0(NumaState, 1);
  30. object_property_add_bool(obj, "hmat",
  31. machine_get_hmat, machine_set_hmat);
  32. object_property_set_description(obj, "hmat",
  33. "Set on/off to enable/disable "
  34. "ACPI Heterogeneous Memory Attribute "
  35. "Table (HMAT)");
  36. }
  37. /* default to mc->default_cpus */
  38. ms->smp.cpus = mc->default_cpus;
  39. ms->smp.max_cpus = mc->default_cpus;
  40. ms->smp.sockets = 1;
  41. ms->smp.dies = 1;
  42. ms->smp.clusters = 1;
  43. ms->smp.cores = 1;
  44. ms->smp.threads = 1;
  45. machine_copy_boot_config(ms, &(BootConfiguration){ 0 });
  46. }

关注此函数中的以下代码:

  1. object_property_add_bool(obj, "hmat",
  2. machine_get_hmat, machine_set_hmat);

代码中的machine_set_machine函数就是传入object_property_add_bool函数的与形参void (*set)(Object *, bool, Error **)对应的实参,也即对于machine对象属性进行设置时实际调用的函数。

对于对象属性的获取接口,机制类似,在下一回中也具体介绍一下。

举报

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