接前一篇文章:QEMU源码全解析26 —— QOM介绍(15)
本文内容参考:
《趣谈Linux操作系统》 —— 刘超,极客时间
《QEMU/KVM》源码解析与应用 —— 李强,机械工业出版社
特此致谢!
前文讲解了对象属性的设置接口。本文讲解对象属性的获取接口。实际上机制是很相似的。
对象属性的设置是通过object_property_get函数来完成的。该函数同样在qom/object.c中,代码如下:
bool object_property_get(Object *obj, const char *name, Visitor *v,Error **errp)
{Error *err = NULL;ObjectProperty *prop = object_property_find_err(obj, name, errp);if (prop == NULL) {return false;}if (!prop->get) {error_setg(errp, QERR_PERMISSION_DENIED);return false;}prop->get(obj, v, name, prop->opaque, &err);error_propagate(errp, err);return !err;
}
其实object_property_get函数只是简单地调用了ObjectProperty的get函数。
每一种属性类型都有自己的get函数,如布尔(bool)、字符串(str)、enum(枚举)等。它们都在qom/object.c中,逐个来看:
static void property_get_str(Object *obj, Visitor *v, const char *name,void *opaque, Error **errp)
{StringProperty *prop = opaque;char *value;Error *err = NULL;value = prop->get(obj, &err);if (err) {error_propagate(errp, err);return;}visit_type_str(v, name, &value, errp);g_free(value);
}
static void property_get_enum(Object *obj, Visitor *v, const char *name,void *opaque, Error **errp)
{EnumProperty *prop = opaque;int value;Error *err = NULL;value = prop->get(obj, &err);if (err) {error_propagate(errp, err);return;}visit_type_enum(v, name, &value, prop->lookup, errp);
}
static void property_get_bool(Object *obj, Visitor *v, const char *name,void *opaque, Error **errp)
{BoolProperty *prop = opaque;bool value;Error *err = NULL;value = prop->get(obj, &err);if (err) {error_propagate(errp, err);return;}visit_type_bool(v, name, &value, errp);
}
仍以bool为例进行讲解。可以看到,property_get_bool函数调用了具体属性(BoolProperty)的get函数,这是在创建这个属性的时候指定的。上一回已经讲过,对象属性的添加是通过object_property_add接口完成的。而bool类型对象属性的添加object_property_add_bool函数则是调用了此接口。object_property_add_bool函数在qom/object.c中,代码如下:
ObjectProperty *
object_property_add_bool(Object *obj, const char *name,bool (*get)(Object *, Error **),void (*set)(Object *, bool, Error **))
{BoolProperty *prop = g_malloc0(sizeof(*prop));prop->get = get;prop->set = set;return object_property_add(obj, name, "bool",get ? property_get_bool : NULL,set ? property_set_bool : NULL,property_release_data,prop);
}
从这个函数中就可以看到,BoolProperty结构的set成员函数为调用object_property_add_bool函数时传入的参数,形参为:void (*get)(Object *, Error **)。在object_property_add_bool函数中调用了上边的property_get_bool函数,在property_set_bool函数中最终调用了形参void (*get)(Object *, Error **)对应的实参,即真正对象属性的获取函数。
仍以machine为例,hw/core/machine.c的machine_initfn函数代码如下:
static void machine_initfn(Object *obj)
{MachineState *ms = MACHINE(obj);MachineClass *mc = MACHINE_GET_CLASS(obj);container_get(obj, "/peripheral");container_get(obj, "/peripheral-anon");ms->dump_guest_core = true;ms->mem_merge = true;ms->enable_graphics = true;ms->kernel_cmdline = g_strdup("");ms->ram_size = mc->default_ram_size;ms->maxram_size = mc->default_ram_size;if (mc->nvdimm_supported) {Object *obj = OBJECT(ms);ms->nvdimms_state = g_new0(NVDIMMState, 1);object_property_add_bool(obj, "nvdimm",machine_get_nvdimm, machine_set_nvdimm);object_property_set_description(obj, "nvdimm","Set on/off to enable/disable ""NVDIMM instantiation");object_property_add_str(obj, "nvdimm-persistence",machine_get_nvdimm_persistence,machine_set_nvdimm_persistence);object_property_set_description(obj, "nvdimm-persistence","Set NVDIMM persistence""Valid values are cpu, mem-ctrl");}if (mc->cpu_index_to_instance_props && mc->get_default_cpu_node_id) {ms->numa_state = g_new0(NumaState, 1);object_property_add_bool(obj, "hmat",machine_get_hmat, machine_set_hmat);object_property_set_description(obj, "hmat","Set on/off to enable/disable ""ACPI Heterogeneous Memory Attribute ""Table (HMAT)");}/* default to mc->default_cpus */ms->smp.cpus = mc->default_cpus;ms->smp.max_cpus = mc->default_cpus;ms->smp.sockets = 1;ms->smp.dies = 1;ms->smp.clusters = 1;ms->smp.cores = 1;ms->smp.threads = 1;machine_copy_boot_config(ms, &(BootConfiguration){ 0 });
}
关注此函数中的以下代码:
object_property_add_bool(obj, "hmat",machine_get_hmat, machine_set_hmat);
代码中的machine_get_machine函数就是传入object_property_add_bool函数的与形参bool (*get)(Object *, Error **)对应的实参,也即对于machine对象属性进行获取时实际调用的函数。
至此,
对象的属性的添加、设置和获取就讲解完了。下一回开始讲解类的属性的添加、设置和获取。