接前一篇文章: QEMU源码全解析25 —— QOM介绍(14)
本文内容参考:
《 QEMU /KVM》源码解析与应用 —— 李强,机械工业出版社
特此致谢!
前文讲解了对象属性的添加接口。本文讲解对象属性的设置接口。
对象属性的设置是通过object_property_set函数来完成的。该函数同样在qom/object.c中,代码如下:
- bool object_property_set(Object *obj, const char *name, Visitor *v,
- Error **errp)
- {
- ERRP_GUARD();
- ObjectProperty *prop = object_property_find_err(obj, name, errp);
-
- if (prop == NULL) {
- return false;
- }
-
- if (!prop->set) {
- error_setg(errp, QERR_PERMISSION_DENIED);
- return false;
- }
- prop->set(obj, v, name, prop->opaque, errp);
- return !*errp;
- }
其实object_property_set函数只是简单地调用了ObjectProperty的set函数。
每一种属性类型都有自己的set函数,如布尔(bool)、字符串(str)、enum(枚举)等。它们都在qom/object.c中,逐个来看:
- static void property_set_str(Object *obj, Visitor *v, const char *name,
- void *opaque, Error **errp)
- {
- StringProperty *prop = opaque;
- char *value;
-
- if (!visit_type_str(v, name, &value, errp)) {
- return;
- }
-
- prop->set(obj, value, errp);
- g_free(value);
- }
- static void property_set_enum(Object *obj, Visitor *v, const char *name,
- void *opaque, Error **errp)
- {
- EnumProperty *prop = opaque;
- int value;
-
- if (!visit_type_enum(v, name, &value, prop->lookup, errp)) {
- return;
- }
- prop->set(obj, value, errp);
- }
- static void property_set_bool(Object *obj, Visitor *v, const char *name,
- void *opaque, Error **errp)
- {
- BoolProperty *prop = opaque;
- bool value;
-
- if (!visit_type_bool(v, name, &value, errp)) {
- return;
- }
-
- prop->set(obj, value, errp);
- }
以bool为例进行讲解。可以看到,property_set_bool函数调用了具体属性(BoolProperty)的set函数,这是在创建这个属性的时候指定的。上一回已经讲过,对象属性的添加是通过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 (*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函数代码如下:
- 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_set_machine函数就是传入object_property_add_bool函数的与形参void (*set)(Object *, bool, Error **)对应的实参,也即对于machine对象属性进行设置时实际调用的函数。
对于对象属性的获取接口,机制类似,在下一回中也具体介绍一下。