QEMU源码分析-QOM
本文最后更新于:8 天前
QOM简介
QOM(QEMU Object Model)是QEMU的一个模块,用于描述虚拟机的结构,包括虚拟机的CPU、内存、硬盘、网络、输入输出设备等。QEMU 为了方便整个系统的构建,实现了自己的一套的面向对象机制,也就是QOM(QEMU Object Model)。
QOM中的面向对象
继承
在 QEMU 中通过 TypeInfo 来定义一个类。
例如 x86_base_cpu_type_info
就是一个 class
,
1 |
|
利用结构体包含来实现继承。这应该是所有的语言实现继承的方法,在 C++ 中,结构体包含的操作被语言内部实现了,而 C 语言需要自己实现。
例如 x86_cpu_type_info
的 parent
是 cpu_type_info
, 他们的结构体分别是 X86CPU
和 CPUState
。
1 |
|
在 X86CPU
中包含一个 CPUState
。
1 |
|
静态成员
静态成员变量可以在类的多个对象中访问,但是要在类外声明。不同对象访问的其实是同一个实体,静态成员变量被多个对象共享。
1 |
|
其中 X86CPU
描述的是非静态成员,而 X86CPUClass
描述的是静态的成员。也就是说class_init
初始化静态成员,instance_init
初始化非静态成员。
那么何时初始化静态成员呢?首先得告诉系统,咱有class_init
这个初始化函数,等需要的时候随时可以调用它初始化,所有先解决如何将这个初始化函数注册到系统中?
在target/i386/cpu.c
最后使用了type_init
。在qemu/include/qemu/module.h
中有一个type_init
宏定义,除了type_init
还有其他宏,比如block_init
,opts_init
等。每个宏都表示一类module
,通过module_init
构造出来。我们展开这个宏,
1 |
|
通过 gcc
扩展属性__attribute__((constructor))
可以让 do_qemu_init_x86_cpu_register_types
在运行 main
函数之前运行。 register_module_init
会让 x86_cpu_register_types
这个函数挂载到 init_type_list[MODULE_INIT_QOM]
这个链表上。
到底,所有的 TypeInfo
通过 type_init
都被放到 type_table
上了,之后通过 Typeinfo
的名称调用 type_table_lookup
获取到 TypeImpl
了。
到这里,将TYPE_X86_CPU
注册进类系统,包括其初始化函数,这部分也就是QEMU中类型的构造。那么何时调用静态成员初始化函数呢?也就是类型的初始化。
静态成员是所有的对象公用的,其初始化显然要发生在所有的对象初始化之前。
1 |
|
select_machine
需要获取所有的 TYPE_MACHINE
的 class
, 其首先会调用所有的 class_list
,其会遍历 type_table
,遍历的过程中会顺带 type_initialize
所有的 TypeImpl
进而调用的 class_init
。
说完类型的初始化,再讲一下对象的初始化,也就是初始化非静态成员,也就是instance_init
在何时被调用?
对象初始化,通过调用 object_new
来实现初始化。
object_initialize_with_type
- 初始化一个空的 :
Object::properties
object_init_with_type
- 如果
object
有parent
,那么调用object_init_with_type
首先初始化parent
的 - 调用
TypeImpl::instance_init
- 如果
- 初始化一个空的 :
1 |
|
动态类型装换(dynamic cast)
多态
参考
本博客所有文章除特别声明外,均采用 CC BY-SA 4.0 协议 ,转载请注明出处!