QEMU源码全解析25 —— QOM介绍(14)

88 篇文章 19 订阅
本文深入探讨QEMU中的ObjectProperty结构,详细解释了ObjectProperty的各个字段,如name、type、description等,并阐述了Object、ObjectProperty与具体属性之间的关系。文章还介绍了如何添加对象属性,特别是通过object_property_add函数实现,以及涉及到的object_property_find和object_class_property_find函数的工作原理。
摘要由CSDN通过智能技术生成

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

本文内容参考:

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

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

特此致谢!

本文开始对于属性ObjectProperty进行深入讲解。

ObjectProperty结构在include/qom/object.h中定义,代码如下:

  1. typedef struct ObjectProperty ObjectProperty;
  2. ……
  3. struct ObjectProperty
  4. {
  5. char *name;
  6. char *type;
  7. char *description;
  8. ObjectPropertyAccessor *get;
  9. ObjectPropertyAccessor *set;
  10. ObjectPropertyResolve *resolve;
  11. ObjectPropertyRelease *release;
  12. ObjectPropertyInit *init;
  13. void *opaque;
  14. QObject *defval;
  15. };

其中:

  • name:表示名字;
  • type:表示属性的类型。如有的属性是字符串,有的是bool类型,有的是link等其它更复杂的类型;
  • description:表示对于属性的描述;
  • get:对属性进行获取;
  • set:对属性进行设置;
  • resolve:对属性进行操作;
  • release:对属性进行释放;
  • opaque:指向一个具体的属性,如BoolProperty等。

每一种具体的属性都会有一个结构体来描述它。例如:表示布尔类型的属性的BoolProperty、表示字符串类型的属性的StringProperty以及表示link类型的属性的LinkProperty。三者都在qom/object.c中定义(不挨着),定义分别如下:

  1. typedef struct {
  2. union {
  3. Object **targetp;
  4. Object *target; /* if OBJ_PROP_LINK_DIRECT, when holding the pointer */
  5. ptrdiff_t offset; /* if OBJ_PROP_LINK_CLASS */
  6. };
  7. void (*check)(const Object *, const char *, Object *, Error **);
  8. ObjectPropertyLinkFlags flags;
  9. } LinkProperty;
  10. ……
  11. typedef struct StringProperty
  12. {
  13. char *(*get)(Object *, Error **);
  14. void (*set)(Object *, const char *, Error **);
  15. } StringProperty;
  16. ……
  17. typedef struct BoolProperty
  18. {
  19. bool (*get)(Object *, Error **);
  20. void (*set)(Object *, bool, Error **);
  21. } BoolProperty;

总结一下Object、ObjectProperty和各个具体属性的关系:

  • Object(struct object)-> GHashTable *properties中存放着属性名到ObjectProperty(struct ObjectProperty)的映射。
  • ObjectProperty -> void *opaque指向一个具体的属性。

下边介绍几个属性的操作接口。属性的添加分为类属性的添加和对象属性的添加。

对于对象属性来说,其属性添加是通过object_property_add接口完成的。object_property_add函数在qom/object.c中,代码如下:

  1. ObjectProperty *
  2. object_property_add(Object *obj, const char *name, const char *type,
  3. ObjectPropertyAccessor *get,
  4. ObjectPropertyAccessor *set,
  5. ObjectPropertyRelease *release,
  6. void *opaque)
  7. {
  8. return object_property_try_add(obj, name, type, get, set, release,
  9. opaque, &error_abort);
  10. }

该函数实际上是object_property_try_add函数的简单封装,object_property_try_add函数就在上边,代码如下:

  1. ObjectProperty *
  2. object_property_try_add(Object *obj, const char *name, const char *type,
  3. ObjectPropertyAccessor *get,
  4. ObjectPropertyAccessor *set,
  5. ObjectPropertyRelease *release,
  6. void *opaque, Error **errp)
  7. {
  8. ObjectProperty *prop;
  9. size_t name_len = strlen(name);
  10. if (name_len >= 3 && !memcmp(name + name_len - 3, "[*]", 4)) {
  11. int i;
  12. ObjectProperty *ret = NULL;
  13. char *name_no_array = g_strdup(name);
  14. name_no_array[name_len - 3] = '\0';
  15. for (i = 0; i < INT16_MAX; ++i) {
  16. char *full_name = g_strdup_printf("%s[%d]", name_no_array, i);
  17. ret = object_property_try_add(obj, full_name, type, get, set,
  18. release, opaque, NULL);
  19. g_free(full_name);
  20. if (ret) {
  21. break;
  22. }
  23. }
  24. g_free(name_no_array);
  25. assert(ret);
  26. return ret;
  27. }
  28. if (object_property_find(obj, name) != NULL) {
  29. error_setg(errp, "attempt to add duplicate property '%s' to object (type '%s')",
  30. name, object_get_typename(obj));
  31. return NULL;
  32. }
  33. prop = g_malloc0(sizeof(*prop));
  34. prop->name = g_strdup(name);
  35. prop->type = g_strdup(type);
  36. prop->get = get;
  37. prop->set = set;
  38. prop->release = release;
  39. prop->opaque = opaque;
  40. g_hash_table_insert(obj->properties, prop->name, prop);
  41. return prop;
  42. }

先不管通配符的情况,即if (name_len >= 3 && !memcmp(name + name_len - 3, "[*]", 4)) 条件判断中的内容,直接跳过往下看。首先调用object_property_find函数来确认所插入的属性是否已经存在。如果已存在,则报错返回,确保不会添加重复的属性。

随后分配一个ObjectProperty结构并使用函数参数进行初始化。代码片段如下:

  1. prop = g_malloc0(sizeof(*prop));
  2. prop->name = g_strdup(name);
  3. prop->type = g_strdup(type);
  4. prop->get = get;
  5. prop->set = set;
  6. prop->release = release;
  7. prop->opaque = opaque;

最后,调用以下代码将其插入到对象的properties域中,并返回此prop:

g_hash_table_insert(obj->properties, prop->name, prop);

翻回头来,看一下object_property_find函数的具体实现。object_property_find函数在同文件(qom/object.c)中,代码如下:

  1. ObjectProperty *object_property_find(Object *obj, const char *name)
  2. {
  3. ObjectProperty *prop;
  4. ObjectClass *klass = object_get_class(obj);
  5. prop = object_class_property_find(klass, name);
  6. if (prop) {
  7. return prop;
  8. }
  9. return g_hash_table_lookup(obj->properties, name);
  10. }

此函数首先调用object_get_class函数由Object结构对象(的指针)obj得到ObjectClass对象(的指针)kclass。object_get_class函数在qom/object.c中,代码如下:

  1. ObjectClass *object_get_class(Object *obj)
  2. {
  3. return obj->class;
  4. }

然后,调用object_class_property_find函数以确认自己所属的类以及所有父类都不存在这个属性。object_class_property_find函数同样在qom/object.c中,代码如下:

  1. ObjectProperty *object_class_property_find(ObjectClass *klass, const char *name)
  2. {
  3. ObjectClass *parent_klass;
  4. parent_klass = object_class_get_parent(klass);
  5. if (parent_klass) {
  6. ObjectProperty *prop =
  7. object_class_property_find(parent_klass, name);
  8. if (prop) {
  9. return prop;
  10. }
  11. }
  12. return g_hash_table_lookup(klass->properties, name);
  13. }

最后,在遍历(递归)完所有父类之后,调用g_hash_table_lookup(obj->properties, name);在自己的域中查找。

欲知后事如何,且看下回分解。

举报

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