接前一篇文章: QEMU源码全解析28 —— QOM介绍(17)
本文内容参考:
《 QEMU /KVM》源码解析与应用 —— 李强,机械工业出版社
特此致谢!
前文讲解了类属性的添加接口。本文讲解类属性的设置及获取接口。
每一种类属性都有自己的add函数,如布尔(bool)、字符串(str)、enum(枚举)等。它们都在qom/object.c中,逐个来看:
- ObjectProperty *
- object_class_property_add_bool(ObjectClass *klass, 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_class_property_add(klass, name, "bool",
- get ? property_get_bool : NULL,
- set ? property_set_bool : NULL,
- NULL,
- prop);
- }
- ObjectProperty *
- object_class_property_add_enum(ObjectClass *klass, const char *name,
- const char *typename,
- const QEnumLookup *lookup,
- int (*get)(Object *, Error **),
- void (*set)(Object *, int, Error **))
- {
- EnumProperty *prop = g_malloc(sizeof(*prop));
-
- prop->lookup = lookup;
- prop->get = get;
- prop->set = set;
-
- return object_class_property_add(klass, name, typename,
- get ? property_get_enum : NULL,
- set ? property_set_enum : NULL,
- NULL,
- prop);
- }
- ObjectProperty *
- object_class_property_add_str(ObjectClass *klass, const char *name,
- char *(*get)(Object *, Error **),
- void (*set)(Object *, const char *,
- Error **))
- {
- StringProperty *prop = g_malloc0(sizeof(*prop));
-
- prop->get = get;
- prop->set = set;
-
- return object_class_property_add(klass, name, "string",
- get ? property_get_str : NULL,
- set ? property_set_str : NULL,
- NULL,
- prop);
- }
这次以str为例进行讲解。上一回已经讲过,类属性的添加是通过object_class_property_add接口完成的。而str类型属性的添加object_class_property_add_str函数则是调用了此接口。为了便于理解,再次贴出object_class_property_add函数代码,在qom/object.c中,如下:
- ObjectProperty *
- object_class_property_add(ObjectClass *klass,
- const char *name,
- const char *type,
- ObjectPropertyAccessor *get,
- ObjectPropertyAccessor *set,
- ObjectPropertyRelease *release,
- void *opaque)
- {
- ObjectProperty *prop;
-
- assert(!object_class_property_find(klass, name));
-
- prop = g_malloc0(sizeof(*prop));
-
- prop->name = g_strdup(name);
- prop->type = g_strdup(type);
-
- prop->get = get;
- prop->set = set;
- prop->release = release;
- prop->opaque = opaque;
-
- g_hash_table_insert(klass->properties, prop->name, prop);
-
- return prop;
- }
property_set_str和property_get_str函数在前文都已给出过,这里再贴一下,在同文件(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_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);
- }
从这两个函数中就可以看到,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函数代码如下:
- static void machine_class_init(ObjectClass *oc, void *data)
- {
- MachineClass *mc = MACHINE_CLASS(oc);
-
- /* Default 128 MB as guest ram size */
- mc->default_ram_size = 128 * MiB;
- mc->rom_file_has_mr = true;
-
- /* numa node memory size aligned on 8MB by default.
- * On Linux, each node's border has to be 8MB aligned
- */
- mc->numa_mem_align_shift = 23;
-
- object_class_property_add_str(oc, "kernel",
- machine_get_kernel, machine_set_kernel);
- object_class_property_set_description(oc, "kernel",
- "Linux kernel image file");
-
- object_class_property_add_str(oc, "initrd",
- machine_get_initrd, machine_set_initrd);
- object_class_property_set_description(oc, "initrd",
- "Linux initial ramdisk file");
-
- object_class_property_add_str(oc, "append",
- machine_get_append, machine_set_append);
- object_class_property_set_description(oc, "append",
- "Linux kernel command line");
-
- object_class_property_add_str(oc, "dtb",
- machine_get_dtb, machine_set_dtb);
- object_class_property_set_description(oc, "dtb",
- "Linux kernel device tree file");
-
- object_class_property_add_str(oc, "dumpdtb",
- machine_get_dumpdtb, machine_set_dumpdtb);
- object_class_property_set_description(oc, "dumpdtb",
- "Dump current dtb to a file and quit");
-
- object_class_property_add(oc, "boot", "BootConfiguration",
- machine_get_boot, machine_set_boot,
- NULL, NULL);
- object_class_property_set_description(oc, "boot",
- "Boot configuration");
-
- object_class_property_add(oc, "smp", "SMPConfiguration",
- machine_get_smp, machine_set_smp,
- NULL, NULL);
- object_class_property_set_description(oc, "smp",
- "CPU topology");
-
- object_class_property_add(oc, "phandle-start", "int",
- machine_get_phandle_start, machine_set_phandle_start,
- NULL, NULL);
- object_class_property_set_description(oc, "phandle-start",
- "The first phandle ID we may generate dynamically");
-
- object_class_property_add_str(oc, "dt-compatible",
- machine_get_dt_compatible, machine_set_dt_compatible);
- object_class_property_set_description(oc, "dt-compatible",
- "Overrides the \"compatible\" property of the dt root node");
-
- object_class_property_add_bool(oc, "dump-guest-core",
- machine_get_dump_guest_core, machine_set_dump_guest_core);
- object_class_property_set_description(oc, "dump-guest-core",
- "Include guest memory in a core dump");
-
- object_class_property_add_bool(oc, "mem-merge",
- machine_get_mem_merge, machine_set_mem_merge);
- object_class_property_set_description(oc, "mem-merge",
- "Enable/disable memory merge support");
-
- object_class_property_add_bool(oc, "usb",
- machine_get_usb, machine_set_usb);
- object_class_property_set_description(oc, "usb",
- "Set on/off to enable/disable usb");
-
- object_class_property_add_bool(oc, "graphics",
- machine_get_graphics, machine_set_graphics);
- object_class_property_set_description(oc, "graphics",
- "Set on/off to enable/disable graphics emulation");
-
- object_class_property_add_str(oc, "firmware",
- machine_get_firmware, machine_set_firmware);
- object_class_property_set_description(oc, "firmware",
- "Firmware image");
-
- object_class_property_add_bool(oc, "suppress-vmdesc",
- machine_get_suppress_vmdesc, machine_set_suppress_vmdesc);
- object_class_property_set_description(oc, "suppress-vmdesc",
- "Set on to disable self-describing migration");
-
- object_class_property_add_link(oc, "confidential-guest-support",
- TYPE_CONFIDENTIAL_GUEST_SUPPORT,
- offsetof(MachineState, cgs),
- machine_check_confidential_guest_support,
- OBJ_PROP_LINK_STRONG);
- object_class_property_set_description(oc, "confidential-guest-support",
- "Set confidential guest scheme to support");
-
- /* For compatibility */
- object_class_property_add_str(oc, "memory-encryption",
- machine_get_memory_encryption, machine_set_memory_encryption);
- object_class_property_set_description(oc, "memory-encryption",
- "Set memory encryption object to use");
-
- object_class_property_add_link(oc, "memory-backend", TYPE_MEMORY_BACKEND,
- offsetof(MachineState, memdev), object_property_allow_set_link,
- OBJ_PROP_LINK_STRONG);
- object_class_property_set_description(oc, "memory-backend",
- "Set RAM backend"
- "Valid value is ID of hostmem based backend");
-
- object_class_property_add(oc, "memory", "MemorySizeConfiguration",
- machine_get_mem, machine_set_mem,
- NULL, NULL);
- object_class_property_set_description(oc, "memory",
- "Memory size configuration");
- }
此函数中很多地方调用了object_class_property_add_str函数,以其中之一为例:
- object_class_property_add_str(oc, "kernel",
- machine_get_kernel, machine_set_kernel);
代码中的machine_set_kernel和machine_get_kernel函数就是传入object_class_property_add_str函数的与形参对应的实参,也即对于machine类的属性进行设置和获取时实际调用的函数。
至此, QEMU 中的QOM相关的内容就简要介绍完了。欲知后事如何,且看下回分解。