Qemu对象模型(QOM)

1. Qemu类型系统

Qemu目前主要是C语言编写(有少量Rust),C语言没有语言层面的面向对象支持,所以Qemu开发团队就为Qemu设计了一套对象系统,我们本专题要讲的就是Qemu的对象系统。
在Qemu代码中,我们经常看到如下代码:

1
type_init(<class_name>_register_types);
  • <class_name>_register_types: Qemu中定义一个类型后通过type_init宏函数来注册该类型。

下面我们就来看一下type_init宏函数的定义:

1
2
// include/qemu/module.h
#define type_init(function) module_init(function, MODULE_INIT_QOM);  
  • function: 类型注册函数;
  • MODULE_INIT_QOM: Qemu对象模型模块;

module_init也是一个宏函数,它的定义如下:

1
2
3
4
5
#define module_init(function, type)                                         \
static void __attribute__((constructor)) do_qemu_init_ ## function(void)    \
{                                                                           \
    register_module_init(function, type);                                   \
}

首先我们分析一下这个宏函数:

  1. 使用了##,用于拼接,例如function是“cpu_register_types”,结果就是do_qemu_init_cpu_register_types,这样可以避免命名冲突,确保每个模块的注册函数独立存在。
  2. __attribute__((constructor)),GCC的一个函数属性,由该属性标记的函数,会在main函数前面执行。
  3. 实际上,这个宏函数就是将用户设计好的类型注册到一个Hash表中,也就是type(类型名称)和function(类型注册函数)。

1.1. 类型注册

上面我们提到了register_module_init,这个函数定义如下:

 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
13
14
// util/module.c  
void register_module_init(void (*fn)(void), module_init_type type)
{
    ModuleEntry *e;
    ModuleTypeList *l;

    e = g_malloc0(sizeof(*e));
    e->init = fn;
    e->type = type;

    l = find_type(type);

    QTAILQ_INSERT_TAIL(l, e, node);
}

这个函数在main函数前就会被执行,它包含了4个知识点,下面我们一一讲解:

1.2. ModuleEntry类型

1
2
3
4
5
6
typedef struct ModuleEntry
{
    void (*init)(void);     // 类型注册函数,就是type_init(<class_name>_register_types);中的<class_name>_register_types
    QTAILQ_ENTRY(ModuleEntry) node;
    module_init_type type;  // 所属模块类型,类型系统就是MODULE_INIT_QOM
} ModuleEntry;

关于

comments powered by Disqus