From 32ce4600179c79c99ae45667c6241d099a1b83af Mon Sep 17 00:00:00 2001 From: jl-jiang Date: Sat, 30 Sep 2023 21:11:29 +0800 Subject: [PATCH 01/11] finish article --- ...20230830-qemu-system-device-model-part3.md | 301 ++++++++++++++++++ articles/assets/datastructure.svg | 4 + .../datastructure.svg | 4 + 3 files changed, 309 insertions(+) create mode 100644 articles/20230830-qemu-system-device-model-part3.md create mode 100644 articles/assets/datastructure.svg create mode 100644 articles/images/qemu-system-device-model-part3/datastructure.svg diff --git a/articles/20230830-qemu-system-device-model-part3.md b/articles/20230830-qemu-system-device-model-part3.md new file mode 100644 index 0000000..e0c26ba --- /dev/null +++ b/articles/20230830-qemu-system-device-model-part3.md @@ -0,0 +1,301 @@ +> Corrector: [TinyCorrect](https://gitee.com/tinylab/tinycorrect) v0.2-rc2 - [urls]
+> Author: jl-jiang
+> Date: 2023/08/30
+> Revisor: Bin Meng
+> Project: [RISC-V Linux 内核剖析](https://gitee.com/tinylab/riscv-linux)
+> Proposal: [【老师提案】QEMU 系统模拟模式分析](https://gitee.com/tinylab/riscv-linux/issues/I61KIY)
+> Sponsor: PLCT Lab, ISCAS + +# QEMU 设备模型简析(三):QOM 设计实现 + +## 前言 + +在[上一篇文章](https://gitee.com/tinylab/riscv-linux/blob/master/articles/20230822-qemu-system-device-model-part2.md)中我们聚焦 QEMU 中面向对象的设备管理机制,阐述了引入对象模型的必要性,介绍了 QOM 基本功能和顶层设计,本文将在此基础上进一步深入,详细分析 QOM 对象系统的设计思路以及实现方式。 + +## 关键结构 + +通过之前的分析,我们已经知道 QOM 有如下几大关键数据结构:`Object`、`ObjectClass`、`TypeInfo` 和 `TypeImpl`,他们的关系如下图所示: + +![](assets/datastructure.svg) + +通过上图不难看出,QOM 对象模型的核心结构是 `Object`,这个结构体十分简洁,只保存了有关类型和父类的信息。`ObjectClass` 结构体就比较复杂,保存指向类型信息 `TypeImpl` 结构体的指针,保证了能够获取有关类型的信息。`TypeImpl` 存储着一个类型的信息,包括类型名称、类型大小、是否抽象类、父类名称、父类类型指针、`ObjectClass`等。`TypeInfo` 结构体没有直接与其他任何数据结构产生直接关联,通过前面的分析我们已经知道,这是面向开发者的一个工具结构,主要用于在注册类型的时候提供类型的基本信息,在类型注册伊始,QEMU 会自动生成对应的 `TypeImpl` 结构体,保存类型的全部信息。 + +## 面向对象特性 + +首先,我们需要回顾一下面向对象的基本特征: + +- 封装 +- 接口 +- 继承 +- 析构 +- 静态成员 +- 多态 +- 动态类型装换 + +下面我们将详细分析上述特性在 QOM 对象系统中的具体实现。 + +### 封装 + +在分析 QOM 如何实现封装之前,我们需要再次回顾 `Object` 结构体的定义: + +```c +/* include/qom/object.h: 153 */ + +struct Object +{ + /* private: */ + ObjectClass *class; + ObjectFree *free; + GHashTable *properties; + uint32_t ref; + Object *parent; +}; +``` + +这里需要关注的是第一行的注释,它表示结构体中的所有属性都是私有的,只能被类的内部成员访问和修改。但是,仅靠 C 语言中的结构体是无法实现对私有变量的访问控制的,因此 QEMU 在 `Object` 中引入了属性表,即 `properties` 指针,它指向一张哈希表,该表含了 `Object` 中的所有可以访问、修改的数据和函数其中每一个键值对表示 `property` 的名称以及指向相应 `ObjectProperty` 结构体的指针。下面给出 `ObjectProperty` 结构体的实现代码: + +```c +/* include/qom/object.h: 88 */ + +struct ObjectProperty +{ + char *name; + char *type; + char *description; + ObjectPropertyAccessor *get; + ObjectPropertyAccessor *set; + ObjectPropertyResolve *resolve; + ObjectPropertyRelease *release; + ObjectPropertyInit *init; + void *opaque; + QObject *defval; +}; +``` + +可以看到,`ObjectProperty` 结构体包含了这个属性的名称、类型、描述、读写方法以及解析和释放函数,还包括这个 `property` 特有的属性,使用 `opaque` 指针来表示。QOM 通过 `ObjectProperty` 结构体将对象的每个数据都保存在这样一个单元之中,再利用一个哈希表实现对对象所有数据的统一管理,进而实现了数据封装。当用户需要向 `Object` 中增加属性时,需要调用 `object_property_add` 函数: + +```c +/* qom/object.c: 1257 */ + +ObjectProperty * +object_property_add(Object *obj, const char *name, const char *type, + ObjectPropertyAccessor *get, + ObjectPropertyAccessor *set, + ObjectPropertyRelease *release, + void *opaque) +{ + return object_property_try_add(obj, name, type, get, set, release, + opaque, &error_abort); +} +``` + +该函数通过进一步调用 `object_property_try_add` 函数向 `properties` 所指向的哈希表中插入了一个新的属性: + +```c +/* qom/object.c: 1206 */ + +ObjectProperty * +object_property_try_add(Object *obj, const char *name, const char *type, + ObjectPropertyAccessor *get, + ObjectPropertyAccessor *set, + ObjectPropertyRelease *release, + void *opaque, Error **errp) +{ + ObjectProperty *prop; + size_t name_len = strlen(name); + + if (name_len >= 3 && !memcmp(name + name_len - 3, "[*]", 4)) { + int i; + ObjectProperty *ret = NULL; + char *name_no_array = g_strdup(name); + + name_no_array[name_len - 3] = '\0'; + for (i = 0; i < INT16_MAX; ++i) { + char *full_name = g_strdup_printf("%s[%d]", name_no_array, i); + + ret = object_property_try_add(obj, full_name, type, get, set, + release, opaque, NULL); + g_free(full_name); + if (ret) { + break; + } + } + g_free(name_no_array); + assert(ret); + return ret; + } + + if (object_property_find(obj, name) != NULL) { + error_setg(errp, "attempt to add duplicate property '%s' to object (type '%s')", + name, object_get_typename(obj)); + return NULL; + } + + 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(obj->properties, prop->name, prop); + return prop; +} +``` + +### 继承 + +再面向对象编程中主要包括三种继承形式: + +- **可视继承:** QEMU 中可视继承主要用于处理图形界面的相关问题,这里不做深入讨论 +- **实现继承:** 子类能够直接使用基类的属性和方法而无需重新编写代码 +- **接口继承:** 子类仅使用基类的属性和方法名称,属性和代码的具体内容需要重新编写代码实现 + +对于实现继承,QOM 通过结构体的包含关系完成。在 QEMU 中我们创建一个新类时,会实现两个数据结构:类的数据结构 `ObjectClass` 和对象的数据结构 `Object`,由于这两个结构体中的第一个成员变量就是父类(对象),那么只要通过 ”指针 + 偏移量“ 就可以直接使用父类的属性和方法,完成了实现继承的功能。 + +对于接口继承,QEMU 中定义了专门的接口结构: + +```c +/* include/qom/object.h: 514 */ + +struct InterfaceClass +{ + ObjectClass parent_class; + /* private: */ + ObjectClass *concrete_class; + Type interface_type; +}; +``` + +在 QOM 中一个类可以实现多个接口,也就是接口继承。`ObjectClass` 结构体中与接口继承相关的属性是 `interfaces`,它指向一条链表,链表中的每个元素都是一个指向 `InterfaceClass` 的指针,再通过其中的 `interface_type` 指针指向一个 `TypeImpl` 结构体,我们可以通过给该指针指向的 `TypeImpl` 结构体中的函数指针赋值,从而达到实现对应接口的目的。 + +### 多态 + +多态是同一操作作用于不同的对象,可以有不同的解释,产生不同的执行结果。为了实现多态,QOM 实现了一个非常重要的功能,即动态强制类型转换(dynamic cast)。我们可以使用相关的函数,将一个 `Object` 的指针在运行时 cast 为子类对象的指针,可以将一个 `ObjectClass` 的指针在运行时 cast 为子类的指针。这样就可以调用子类中定义的函数指针来完成相应的功能。动态 cast 功能主要由 `object_class_dynamic_cast` 函数实现: + +```c +/* qom/object.c: 908 */ + +ObjectClass *object_class_dynamic_cast(ObjectClass *class, + const char *typename) +{ + ObjectClass *ret = NULL; + TypeImpl *target_type; + TypeImpl *type; + + if (!class) { + return NULL; + } + + /* A simple fast path that can trigger a lot for leaf classes. */ + type = class->type; + if (type->name == typename) { + return class; + } + + target_type = type_get_by_name(typename); + if (!target_type) { + /* target class type unknown, so fail the cast */ + return NULL; + } + + if (type->class->interfaces && + type_is_ancestor(target_type, type_interface)) { + int found = 0; + GSList *i; + + for (i = class->interfaces; i; i = i->next) { + ObjectClass *target_class = i->data; + + if (type_is_ancestor(target_class->type, target_type)) { + ret = target_class; + found++; + } + } + + /* The match was ambiguous, don't allow a cast */ + if (found > 1) { + ret = NULL; + } + } else if (type_is_ancestor(type, target_type)) { + ret = class; + } + + return ret; +} +``` + +### 析构 + +QOM 的通过 “引用计数” 来判断何时调用析构函数删除对象,`Object` 的结构体中有一个专门用于对 `Object` 引用的计数变量 `ref`,如果 `ref` 的值减少为 0,就意味着系统不会继续使用这个对象了,那么就可以对相应的内存空间等进行回收操作: + +```c +/* qom/object.c: 1192 */ + +void object_unref(void *objptr) +{ + Object *obj = OBJECT(objptr); + if (!obj) { + return; + } + g_assert(obj->ref > 0); + + /* parent always holds a reference to its children */ + if (qatomic_fetch_dec(&obj->ref) == 1) { + object_finalize(obj); + } +} +``` + +在注册类型时,可以通过定义 `TypeInfo` 结构体中的 `instance_finalize` 实现自定义析构函数,对于引用计数为 0 的 `Object` 进行垃圾回收操作。QOM 提供了默认析构函数: + +```c +/* qom/object.c: 688 */ + +static void object_finalize(void *data) +{ + Object *obj = data; + TypeImpl *ti = obj->class->type; + + object_property_del_all(obj); + object_deinit(obj, ti); + + g_assert(obj->ref == 0); + g_assert(obj->parent == NULL); + if (obj->free) { + obj->free(obj); + } +} +``` + +`Object` 数据结构中有一个 `ObjectFree *` 类型的函数指针 `free`,当 `Object` 的引用计数为 0 时,就会调用这个函数进行垃圾回收: + +```c +/* qom/object.c: 677 */ + +static void object_deinit(Object *obj, TypeImpl *type) +{ + if (type->instance_finalize) { + type->instance_finalize(obj); + } + + if (type_has_parent(type)) { + object_deinit(obj, type_get_parent(type)); + } +} +``` + +该函数会调用 `TypeImpl` 中的实例析构函数。如果存在父类,则会递归继续调用父类的实例析构函数。这里之所以需要调用父类实例析构函数是因为一个 `Object` 结构体的第一个成员变量就是父类对象的实例,因此当我们需要对对象析构时,不仅要调用当前类的析构方法,也需要调用父类的析构方法将结构体中的第一个成员进行析构。 + +## 总结 + +QOM 实现了一套较为完备的对象管理系统,包括自动化的对象注册、完善的对象管理以及巧妙的动态类型转换,本文梳理了 QOM 实现中几大关键数据结构之间的联系,详细分析了封装、多态、继承以及析构等面向对象特性在 QOM 中的集体实现,与之前的文章相呼应,打通了 QEMU 设备模型从使用到实现的全过程逻辑链条。 + +## 参考资料 + +- [Kvmforum14-qom.pdf](https://www.linux-kvm.org/images/9/90/Kvmforum14-qom.pdf) + +- [QOM实现分析](http://blog.chinaunix.net/uid-28541347-id-5784376.html) diff --git a/articles/assets/datastructure.svg b/articles/assets/datastructure.svg new file mode 100644 index 0000000..2c04f83 --- /dev/null +++ b/articles/assets/datastructure.svg @@ -0,0 +1,4 @@ + + + +
type
type
interfaces
interfaces
...
...
properties
properties
ObjectClass
ObjectClass
class
class
free
free
properties
properties
ref
ref
parent
parent
Object
Object
name
name
type
type
...
...
defval
defval
ObjectProperty
ObjectProperty
name
name
class
class
...
...
interfaces
interfaces
TypeImpl
TypeImpl
name
name
class
class
...
...
interfaces
interfaces
TypeInfo
TypeInfo
name
name
type
type
...
...
defval
defval
ObjectProperty
ObjectProperty
...
...
properties
properties
Text is not SVG - cannot display
\ No newline at end of file diff --git a/articles/images/qemu-system-device-model-part3/datastructure.svg b/articles/images/qemu-system-device-model-part3/datastructure.svg new file mode 100644 index 0000000..2c04f83 --- /dev/null +++ b/articles/images/qemu-system-device-model-part3/datastructure.svg @@ -0,0 +1,4 @@ + + + +
type
type
interfaces
interfaces
...
...
properties
properties
ObjectClass
ObjectClass
class
class
free
free
properties
properties
ref
ref
parent
parent
Object
Object
name
name
type
type
...
...
defval
defval
ObjectProperty
ObjectProperty
name
name
class
class
...
...
interfaces
interfaces
TypeImpl
TypeImpl
name
name
class
class
...
...
interfaces
interfaces
TypeInfo
TypeInfo
name
name
type
type
...
...
defval
defval
ObjectProperty
ObjectProperty
...
...
properties
properties
Text is not SVG - cannot display
\ No newline at end of file -- Gitee From 08d98e3dad318cc26cbf32aa79d34506f1dced4a Mon Sep 17 00:00:00 2001 From: jl-jiang Date: Sat, 30 Sep 2023 21:11:43 +0800 Subject: [PATCH 02/11] qemu-system-device-model-part3.md: commit correct result of tinycorrect-comments Signed-off-by: jl-jiang --- articles/20230830-qemu-system-device-model-part3.md | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/articles/20230830-qemu-system-device-model-part3.md b/articles/20230830-qemu-system-device-model-part3.md index e0c26ba..9f7a499 100644 --- a/articles/20230830-qemu-system-device-model-part3.md +++ b/articles/20230830-qemu-system-device-model-part3.md @@ -1,4 +1,4 @@ -> Corrector: [TinyCorrect](https://gitee.com/tinylab/tinycorrect) v0.2-rc2 - [urls]
+> Corrector: [TinyCorrect](https://gitee.com/tinylab/tinycorrect) v0.2-rc2 - [comments]
> Author: jl-jiang
> Date: 2023/08/30
> Revisor: Bin Meng
@@ -190,7 +190,7 @@ ObjectClass *object_class_dynamic_cast(ObjectClass *class, return NULL; } - /* A simple fast path that can trigger a lot for leaf classes. */ + /* A simple fast path that can trigger a lot for leaf classes. */ type = class->type; if (type->name == typename) { return class; -- Gitee From 7e20fdba5b10d51a961588258e17aa45393531e2 Mon Sep 17 00:00:00 2001 From: jl-jiang Date: Sat, 30 Sep 2023 21:12:11 +0800 Subject: [PATCH 03/11] qemu-system-device-model-part3.md: commit correct result of tinycorrect-codeinline Signed-off-by: jl-jiang --- articles/20230830-qemu-system-device-model-part3.md | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/articles/20230830-qemu-system-device-model-part3.md b/articles/20230830-qemu-system-device-model-part3.md index 9f7a499..ca1ece1 100644 --- a/articles/20230830-qemu-system-device-model-part3.md +++ b/articles/20230830-qemu-system-device-model-part3.md @@ -1,4 +1,4 @@ -> Corrector: [TinyCorrect](https://gitee.com/tinylab/tinycorrect) v0.2-rc2 - [comments]
+> Corrector: [TinyCorrect](https://gitee.com/tinylab/tinycorrect) v0.2-rc2 - [comments codeinline]
> Author: jl-jiang
> Date: 2023/08/30
> Revisor: Bin Meng
@@ -18,7 +18,7 @@ ![](assets/datastructure.svg) -通过上图不难看出,QOM 对象模型的核心结构是 `Object`,这个结构体十分简洁,只保存了有关类型和父类的信息。`ObjectClass` 结构体就比较复杂,保存指向类型信息 `TypeImpl` 结构体的指针,保证了能够获取有关类型的信息。`TypeImpl` 存储着一个类型的信息,包括类型名称、类型大小、是否抽象类、父类名称、父类类型指针、`ObjectClass`等。`TypeInfo` 结构体没有直接与其他任何数据结构产生直接关联,通过前面的分析我们已经知道,这是面向开发者的一个工具结构,主要用于在注册类型的时候提供类型的基本信息,在类型注册伊始,QEMU 会自动生成对应的 `TypeImpl` 结构体,保存类型的全部信息。 +通过上图不难看出,QOM 对象模型的核心结构是 `Object`,这个结构体十分简洁,只保存了有关类型和父类的信息。`ObjectClass` 结构体就比较复杂,保存指向类型信息 `TypeImpl` 结构体的指针,保证了能够获取有关类型的信息。`TypeImpl` 存储着一个类型的信息,包括类型名称、类型大小、是否抽象类、父类名称、父类类型指针、`ObjectClass` 等。`TypeInfo` 结构体没有直接与其他任何数据结构产生直接关联,通过前面的分析我们已经知道,这是面向开发者的一个工具结构,主要用于在注册类型的时候提供类型的基本信息,在类型注册伊始,QEMU 会自动生成对应的 `TypeImpl` 结构体,保存类型的全部信息。 ## 面向对象特性 @@ -72,7 +72,7 @@ struct ObjectProperty }; ``` -可以看到,`ObjectProperty` 结构体包含了这个属性的名称、类型、描述、读写方法以及解析和释放函数,还包括这个 `property` 特有的属性,使用 `opaque` 指针来表示。QOM 通过 `ObjectProperty` 结构体将对象的每个数据都保存在这样一个单元之中,再利用一个哈希表实现对对象所有数据的统一管理,进而实现了数据封装。当用户需要向 `Object` 中增加属性时,需要调用 `object_property_add` 函数: +可以看到,`ObjectProperty` 结构体包含了这个属性的名称、类型、描述、读写方法以及解析和释放函数,还包括这个 `property` 特有的属性,使用 `opaque` 指针来表示。QOM 通过 `ObjectProperty` 结构体将对象的每个数据都保存在这样一个单元之中,再利用一个哈希表实现对对象所有数据的统一管理,进而实现了数据封装。当用户需要向 `Object` 中增加属性时,需要调用 `object_property_add` 函数: ```c /* qom/object.c: 1257 */ -- Gitee From 1e282444a7a68c392fca2b44238d03f92d381325 Mon Sep 17 00:00:00 2001 From: jl-jiang Date: Sat, 30 Sep 2023 21:12:17 +0800 Subject: [PATCH 04/11] qemu-system-device-model-part3.md: commit correct result of tinycorrect-images Signed-off-by: jl-jiang --- articles/20230830-qemu-system-device-model-part3.md | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/articles/20230830-qemu-system-device-model-part3.md b/articles/20230830-qemu-system-device-model-part3.md index ca1ece1..e8d48ab 100644 --- a/articles/20230830-qemu-system-device-model-part3.md +++ b/articles/20230830-qemu-system-device-model-part3.md @@ -1,4 +1,4 @@ -> Corrector: [TinyCorrect](https://gitee.com/tinylab/tinycorrect) v0.2-rc2 - [comments codeinline]
+> Corrector: [TinyCorrect](https://gitee.com/tinylab/tinycorrect) v0.2-rc2 - [comments codeinline images]
> Author: jl-jiang
> Date: 2023/08/30
> Revisor: Bin Meng
@@ -16,7 +16,7 @@ 通过之前的分析,我们已经知道 QOM 有如下几大关键数据结构:`Object`、`ObjectClass`、`TypeInfo` 和 `TypeImpl`,他们的关系如下图所示: -![](assets/datastructure.svg) +![datastructure.svg](assets/datastructure.svg) 通过上图不难看出,QOM 对象模型的核心结构是 `Object`,这个结构体十分简洁,只保存了有关类型和父类的信息。`ObjectClass` 结构体就比较复杂,保存指向类型信息 `TypeImpl` 结构体的指针,保证了能够获取有关类型的信息。`TypeImpl` 存储着一个类型的信息,包括类型名称、类型大小、是否抽象类、父类名称、父类类型指针、`ObjectClass` 等。`TypeInfo` 结构体没有直接与其他任何数据结构产生直接关联,通过前面的分析我们已经知道,这是面向开发者的一个工具结构,主要用于在注册类型的时候提供类型的基本信息,在类型注册伊始,QEMU 会自动生成对应的 `TypeImpl` 结构体,保存类型的全部信息。 -- Gitee From b01fb26915afeab38a2018a5fff7100b9b27204c Mon Sep 17 00:00:00 2001 From: jl-jiang Date: Sat, 30 Sep 2023 21:13:08 +0800 Subject: [PATCH 05/11] qemu-system-device-model-part3.md: commit correct result of tinycorrect-refs Signed-off-by: jl-jiang --- articles/20230830-qemu-system-device-model-part3.md | 3 +-- 1 file changed, 1 insertion(+), 2 deletions(-) diff --git a/articles/20230830-qemu-system-device-model-part3.md b/articles/20230830-qemu-system-device-model-part3.md index e8d48ab..261d325 100644 --- a/articles/20230830-qemu-system-device-model-part3.md +++ b/articles/20230830-qemu-system-device-model-part3.md @@ -1,4 +1,4 @@ -> Corrector: [TinyCorrect](https://gitee.com/tinylab/tinycorrect) v0.2-rc2 - [comments codeinline images]
+> Corrector: [TinyCorrect](https://gitee.com/tinylab/tinycorrect) v0.2-rc2 - [comments codeinline images urls refs]
> Author: jl-jiang
> Date: 2023/08/30
> Revisor: Bin Meng
@@ -297,5 +297,4 @@ QOM 实现了一套较为完备的对象管理系统,包括自动化的对象 ## 参考资料 - [Kvmforum14-qom.pdf](https://www.linux-kvm.org/images/9/90/Kvmforum14-qom.pdf) - - [QOM实现分析](http://blog.chinaunix.net/uid-28541347-id-5784376.html) -- Gitee From 2e77cf4aae7219f82b1a6b504d7f0bf1fe4fe147 Mon Sep 17 00:00:00 2001 From: jl-jiang Date: Sat, 30 Sep 2023 21:13:14 +0800 Subject: [PATCH 06/11] qemu-system-device-model-part3.md: commit correct result of tinycorrect-pangu Signed-off-by: jl-jiang --- articles/20230830-qemu-system-device-model-part3.md | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/articles/20230830-qemu-system-device-model-part3.md b/articles/20230830-qemu-system-device-model-part3.md index 261d325..30b188f 100644 --- a/articles/20230830-qemu-system-device-model-part3.md +++ b/articles/20230830-qemu-system-device-model-part3.md @@ -1,4 +1,4 @@ -> Corrector: [TinyCorrect](https://gitee.com/tinylab/tinycorrect) v0.2-rc2 - [comments codeinline images urls refs]
+> Corrector: [TinyCorrect](https://gitee.com/tinylab/tinycorrect) v0.2-rc2 - [comments codeinline images urls refs pangu]
> Author: jl-jiang
> Date: 2023/08/30
> Revisor: Bin Meng
@@ -297,4 +297,4 @@ QOM 实现了一套较为完备的对象管理系统,包括自动化的对象 ## 参考资料 - [Kvmforum14-qom.pdf](https://www.linux-kvm.org/images/9/90/Kvmforum14-qom.pdf) -- [QOM实现分析](http://blog.chinaunix.net/uid-28541347-id-5784376.html) +- [QOM 实现分析](http://blog.chinaunix.net/uid-28541347-id-5784376.html) -- Gitee From 6efa9236785e5c8384804ed8b18a9facdae69aeb Mon Sep 17 00:00:00 2001 From: jl-jiang Date: Sat, 30 Sep 2023 21:13:35 +0800 Subject: [PATCH 07/11] qemu-system-device-model-part3.md: commit correct result of tinycorrect-autocorrect Signed-off-by: jl-jiang --- articles/20230830-qemu-system-device-model-part3.md | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/articles/20230830-qemu-system-device-model-part3.md b/articles/20230830-qemu-system-device-model-part3.md index 30b188f..e4f45c1 100644 --- a/articles/20230830-qemu-system-device-model-part3.md +++ b/articles/20230830-qemu-system-device-model-part3.md @@ -1,4 +1,4 @@ -> Corrector: [TinyCorrect](https://gitee.com/tinylab/tinycorrect) v0.2-rc2 - [comments codeinline images urls refs pangu]
+> Corrector: [TinyCorrect](https://gitee.com/tinylab/tinycorrect) v0.2-rc2 - [comments codeinline images urls refs pangu autocorrect]
> Author: jl-jiang
> Date: 2023/08/30
> Revisor: Bin Meng
@@ -154,7 +154,7 @@ object_property_try_add(Object *obj, const char *name, const char *type, - **实现继承:** 子类能够直接使用基类的属性和方法而无需重新编写代码 - **接口继承:** 子类仅使用基类的属性和方法名称,属性和代码的具体内容需要重新编写代码实现 -对于实现继承,QOM 通过结构体的包含关系完成。在 QEMU 中我们创建一个新类时,会实现两个数据结构:类的数据结构 `ObjectClass` 和对象的数据结构 `Object`,由于这两个结构体中的第一个成员变量就是父类(对象),那么只要通过 ”指针 + 偏移量“ 就可以直接使用父类的属性和方法,完成了实现继承的功能。 +对于实现继承,QOM 通过结构体的包含关系完成。在 QEMU 中我们创建一个新类时,会实现两个数据结构:类的数据结构 `ObjectClass` 和对象的数据结构 `Object`,由于这两个结构体中的第一个成员变量就是父类(对象),那么只要通过”指针 + 偏移量“就可以直接使用父类的属性和方法,完成了实现继承的功能。 对于接口继承,QEMU 中定义了专门的接口结构: -- Gitee From 63f7cd1eea0deca63e601a0a2db8b5e73dcbd04a Mon Sep 17 00:00:00 2001 From: jl-jiang Date: Sat, 30 Sep 2023 21:13:45 +0800 Subject: [PATCH 08/11] qemu-system-device-model-part3.md: commit correct result of tinycorrect-epw Signed-off-by: jl-jiang --- articles/20230830-qemu-system-device-model-part3.md | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/articles/20230830-qemu-system-device-model-part3.md b/articles/20230830-qemu-system-device-model-part3.md index e4f45c1..b6c6a56 100644 --- a/articles/20230830-qemu-system-device-model-part3.md +++ b/articles/20230830-qemu-system-device-model-part3.md @@ -1,4 +1,4 @@ -> Corrector: [TinyCorrect](https://gitee.com/tinylab/tinycorrect) v0.2-rc2 - [comments codeinline images urls refs pangu autocorrect]
+> Corrector: [TinyCorrect](https://gitee.com/tinylab/tinycorrect) v0.2-rc2 - [comments codeinline images urls refs pangu autocorrect epw]
> Author: jl-jiang
> Date: 2023/08/30
> Revisor: Bin Meng
@@ -154,7 +154,7 @@ object_property_try_add(Object *obj, const char *name, const char *type, - **实现继承:** 子类能够直接使用基类的属性和方法而无需重新编写代码 - **接口继承:** 子类仅使用基类的属性和方法名称,属性和代码的具体内容需要重新编写代码实现 -对于实现继承,QOM 通过结构体的包含关系完成。在 QEMU 中我们创建一个新类时,会实现两个数据结构:类的数据结构 `ObjectClass` 和对象的数据结构 `Object`,由于这两个结构体中的第一个成员变量就是父类(对象),那么只要通过”指针 + 偏移量“就可以直接使用父类的属性和方法,完成了实现继承的功能。 +对于实现继承,QOM 通过结构体的包含关系完成。在 QEMU 中我们创建一个新类时,会实现两个数据结构:类的数据结构 `ObjectClass` 和对象的数据结构 `Object`,由于这两个结构体中的第一个成员变量就是父类(对象),那么只要通过“指针 + 偏移量”就可以直接使用父类的属性和方法,完成了实现继承的功能。 对于接口继承,QEMU 中定义了专门的接口结构: -- Gitee From 141047f21a056f9e13f8a977d81262becdeb8533 Mon Sep 17 00:00:00 2001 From: jl-jiang Date: Sat, 30 Sep 2023 21:14:43 +0800 Subject: [PATCH 09/11] qemu-system-device-model-part3.md: commit correct result of tinycorrect-urls Signed-off-by: jl-jiang --- articles/20230830-qemu-system-device-model-part3.md | 12 ++++++++---- 1 file changed, 8 insertions(+), 4 deletions(-) diff --git a/articles/20230830-qemu-system-device-model-part3.md b/articles/20230830-qemu-system-device-model-part3.md index b6c6a56..0933b5e 100644 --- a/articles/20230830-qemu-system-device-model-part3.md +++ b/articles/20230830-qemu-system-device-model-part3.md @@ -1,4 +1,4 @@ -> Corrector: [TinyCorrect](https://gitee.com/tinylab/tinycorrect) v0.2-rc2 - [comments codeinline images urls refs pangu autocorrect epw]
+> Corrector: [TinyCorrect](https://gitee.com/tinylab/tinycorrect) v0.2-rc2 - [urls]
> Author: jl-jiang
> Date: 2023/08/30
> Revisor: Bin Meng
@@ -10,7 +10,7 @@ ## 前言 -在[上一篇文章](https://gitee.com/tinylab/riscv-linux/blob/master/articles/20230822-qemu-system-device-model-part2.md)中我们聚焦 QEMU 中面向对象的设备管理机制,阐述了引入对象模型的必要性,介绍了 QOM 基本功能和顶层设计,本文将在此基础上进一步深入,详细分析 QOM 对象系统的设计思路以及实现方式。 +在[上一篇文章][002]中我们聚焦 QEMU 中面向对象的设备管理机制,阐述了引入对象模型的必要性,介绍了 QOM 基本功能和顶层设计,本文将在此基础上进一步深入,详细分析 QOM 对象系统的设计思路以及实现方式。 ## 关键结构 @@ -296,5 +296,9 @@ QOM 实现了一套较为完备的对象管理系统,包括自动化的对象 ## 参考资料 -- [Kvmforum14-qom.pdf](https://www.linux-kvm.org/images/9/90/Kvmforum14-qom.pdf) -- [QOM 实现分析](http://blog.chinaunix.net/uid-28541347-id-5784376.html) +- [Kvmforum14-qom.pdf][003] +- [QOM 实现分析][001] + +[001]: http://blog.chinaunix.net/uid-28541347-id-5784376.html +[002]: https://gitee.com/tinylab/riscv-linux/blob/master/articles/20230822-qemu-system-device-model-part2.md +[003]: https://www.linux-kvm.org/images/9/90/Kvmforum14-qom.pdf -- Gitee From 2a646897321d995f4f05d9c5a18dfd698dc91105 Mon Sep 17 00:00:00 2001 From: jl-jiang Date: Sat, 30 Sep 2023 21:16:24 +0800 Subject: [PATCH 10/11] qemu-system-device-model-part3.md: commit correct result of tinycorrect-autocorrect Signed-off-by: jl-jiang --- articles/20230830-qemu-system-device-model-part3.md | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/articles/20230830-qemu-system-device-model-part3.md b/articles/20230830-qemu-system-device-model-part3.md index 0933b5e..c14d7f2 100644 --- a/articles/20230830-qemu-system-device-model-part3.md +++ b/articles/20230830-qemu-system-device-model-part3.md @@ -1,4 +1,4 @@ -> Corrector: [TinyCorrect](https://gitee.com/tinylab/tinycorrect) v0.2-rc2 - [urls]
+> Corrector: [TinyCorrect](https://gitee.com/tinylab/tinycorrect) v0.2-rc2 - [urls refs autocorrect]
> Author: jl-jiang
> Date: 2023/08/30
> Revisor: Bin Meng
@@ -10,7 +10,7 @@ ## 前言 -在[上一篇文章][002]中我们聚焦 QEMU 中面向对象的设备管理机制,阐述了引入对象模型的必要性,介绍了 QOM 基本功能和顶层设计,本文将在此基础上进一步深入,详细分析 QOM 对象系统的设计思路以及实现方式。 +在 [上一篇文章][002] 中我们聚焦 QEMU 中面向对象的设备管理机制,阐述了引入对象模型的必要性,介绍了 QOM 基本功能和顶层设计,本文将在此基础上进一步深入,详细分析 QOM 对象系统的设计思路以及实现方式。 ## 关键结构 @@ -154,7 +154,7 @@ object_property_try_add(Object *obj, const char *name, const char *type, - **实现继承:** 子类能够直接使用基类的属性和方法而无需重新编写代码 - **接口继承:** 子类仅使用基类的属性和方法名称,属性和代码的具体内容需要重新编写代码实现 -对于实现继承,QOM 通过结构体的包含关系完成。在 QEMU 中我们创建一个新类时,会实现两个数据结构:类的数据结构 `ObjectClass` 和对象的数据结构 `Object`,由于这两个结构体中的第一个成员变量就是父类(对象),那么只要通过“指针 + 偏移量”就可以直接使用父类的属性和方法,完成了实现继承的功能。 +对于实现继承,QOM 通过结构体的包含关系完成。在 QEMU 中我们创建一个新类时,会实现两个数据结构:类的数据结构 `ObjectClass` 和对象的数据结构 `Object`,由于这两个结构体中的第一个成员变量就是父类(对象),那么只要通过 “指针 + 偏移量” 就可以直接使用父类的属性和方法,完成了实现继承的功能。 对于接口继承,QEMU 中定义了专门的接口结构: -- Gitee From 3c9a6de63cdd1e42a9dc5ff5e02411ed16b5ef9c Mon Sep 17 00:00:00 2001 From: falcon Date: Mon, 2 Oct 2023 06:59:07 +0000 Subject: [PATCH 11/11] Update articles/20230830-qemu-system-device-model-part3.md --- articles/20230830-qemu-system-device-model-part3.md | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/articles/20230830-qemu-system-device-model-part3.md b/articles/20230830-qemu-system-device-model-part3.md index c14d7f2..489fb96 100644 --- a/articles/20230830-qemu-system-device-model-part3.md +++ b/articles/20230830-qemu-system-device-model-part3.md @@ -148,7 +148,7 @@ object_property_try_add(Object *obj, const char *name, const char *type, ### 继承 -再面向对象编程中主要包括三种继承形式: +在面向对象编程中主要包括三种继承形式: - **可视继承:** QEMU 中可视继承主要用于处理图形界面的相关问题,这里不做深入讨论 - **实现继承:** 子类能够直接使用基类的属性和方法而无需重新编写代码 -- Gitee