接口

在一些设备类型定义中我们可以看到interfaces一栏。

static TypeInfo pc_dimm_info = {
    .name          = TYPE_PC_DIMM,
    .parent        = TYPE_DEVICE,
    ...
    .interfaces = (InterfaceInfo[]) {
        { TYPE_MEMORY_DEVICE },
        { }
    },
};

那这一栏是什么意思呢?让我们来进一步打开看看。

Interface也是一种类型

进一步看,可以发现在Qemu模型中接口也是一种类型,并且也有父子关系。

static TypeInfo interface_info = {
    .name = TYPE_INTERFACE,
    .class_size = sizeof(InterfaceClass),
    .abstract = true,
};

static const TypeInfo memory_device_info = {
    .name          = TYPE_MEMORY_DEVICE,
    .parent        = TYPE_INTERFACE,
    .class_size = sizeof(MemoryDeviceClass),
};

但是和普通类型不同,他们只有对应的Class,而没有object。

我们尝试把这两个类型画成图,或许能看得更清楚一些。

                                              +---------------------------------------------------------------+
                                              |                                                               |
                                              v                                                               |
       TypeInfo                               TypeImpl*                       InterfaceClass                  |
       +---------------------+                +----------------------+    +-->+------------------------+      |
       |name                 | type_new()---> |name                  |    |   |parent_class            |      |
       |     TYPE_INTERFACE  |                |    TYPE_INTERFACE    |    |   |   (ObjectClass)        |      |
       +---------------------+                |class              ---|----+   |   type             ----|------+
                                              |    (ObjectClass*)    |        |concrete_class          |
                                              +----------------------+        |   (ObjectClass*)       |
                                                                              |interface_type          |
                                                                              |   (TypeImpl*)          |
                                                                              +------------------------+
                                                                                    |
                                                                                    |
                                                                                    |
                                                                                    v
                                              +---------------------------------------------------------------+
                                              |                                MemoryDeviceClass              |
                                              v                                +--------------------------+   |
       TypeInfo                               TypeImpl*                        |InterfaceClass            |   |
       +---------------------+                +----------------------+    +--> | +------------------------+   |
       |name                 | type_new()---> |name                  |    |    | |parent_class            |   |
       |   TYPE_MEMORY_DEVICE|                |   TYPE_MEMORY_DEVICE |    |    | |   (ObjectClass)        |   |
       +---------------------+                |class              ---|----+    | |   type             ----|---+
                                              |    (ObjectClass*)    |         | |concrete_class          |
                                              +----------------------+         | |   (ObjectClass*)       |
                                                                               | |interface_type          |
                                                                               | |   (TypeImpl*)          |
                                                                               | +------------------------+
                                                                               |get_addr                  |
                                                                               |set_addr                  |
                                                                               |...                       |
                                                                               |                          |
                                                                               +--------------------------+

接口类型附属于设备类型

接口类型是一个很有意思的类型,刚才我们看到了TYPE_MEMORY_DEVICE会对应有一个MemoryDeviceClass。

对于普通的设备类型,那整个系统中就只会有这么一个对应的Class,但是接口类型则不是。

还是从代码上来看:

static void type_initialize(TypeImpl *ti)
{
  ...
  for (i = 0; i < ti->num_interfaces; i++) {
    TypeImpl *t = type_get_by_name(ti->interfaces[i].typename);
    for (e = ti->class->interfaces; e; e = e->next) {
        TypeImpl *target_type = OBJECT_CLASS(e->data)->type;

        if (type_is_ancestor(target_type, t)) {
            break;
        }
    }

    if (e) {
        continue;
    }

    type_initialize_interface(ti, t, t);
  }
  ...
}

对于定义了interfaces成员的类型,在初始化中将通过type_initialize_interface来创建自己的接口类型。 而这个类型不仅在系统中注册,还会添加到class->interfaces链表上。

                                              +----------------------------------------------------------------+-----+
                                              |                                                                |     |
                                              |                                MemoryDeviceClass               |     |
                                              v                                +--------------------------+    |     |
                                              TypeImpl*                        |InterfaceClass            |    |     |
                                              +----------------------+    +--> | +------------------------+    |     |
                                              |name                  |    |    | |parent_class            |    |     |
                                              |   TYPE_MEMORY_DEVICE |    |    | |   (ObjectClass)        |    |     |
                                              |class              ---|----+    | |   type             ----|----+     |
                                              |    (ObjectClass*)    |         | |interface_type          |          |
                                              +----------------------+         | |   (TypeImpl*)          |          |
                                                         ^                     | |concrete_class          |          |
                                                         |                     | |   (ObjectClass*)       |          |
                                                         |                     | +------------------------+          |
                                                         |                     |get_addr                  |          |
                                                         |                     |set_addr                  |          |
                                                         |                     |...                       |          |
                                                         |                     |                          |          |
                                                         |                     +--------------------------+          |
                                                         |                                                           |
                                                         |                                                           |
                                                         |                                                           |
    TypeImpl                                 +----------------------------------------------------------------+      |
    +--------------------------+             |           |                                                    |      |
    |name                      |             |           |                    MemoryDeviceClass               |      |
    |   TYPE_PC_DIMM           |             v           |                    +--------------------------+    |      |
    +--------------------------+             TypeImpl*   |                    |InterfaceClass            |    |      |
               ^                             +----------------------+    +--> | +------------------------+    |      |
               |                             |name                  |    |    | |parent_class            |    |      |
    PCDIMMDeviceClass                        |   TYPE_PC_DIMM::     |    |    | |   (ObjectClass)        |    |      |
    +--------------------------+             |   TYPE_MEMORY_DEVICE |    |    | |   type             ----|----+      |
    |parent_class              |      +----->|class              ---|----+    | |interface_type      ----|-----------+
    |   (ObjectClass)          |      |      |    (ObjectClass*)    |         | |   (TypeImpl*)          |
    |      interfaces      ----|------+      +----------------------+         | |concrete_class      ----|----+
    |                          |                                              | |   (ObjectClass*)       |    |
    +--------------------------+                                              | +------------------------+    |
    ^                                                                         |get_addr                  |    |
    |                                                                         |set_addr                  |    |
    |                                                                         |...                       |    |
    |                                                                         |                          |    |
    |                                                                         +--------------------------+    |
    |                                                                                                         |
    |                                                                                                         |
    +---------------------------------------------------------------------------------------------------------+

希望这个图能够对理解接口有一点点帮助。

设置接口类型的“虚函数”

接口类型重要的成员就是它的虚函数了,那谁在什么时候设置呢?

因为接口类型是从属于设备类型的,所以虚函数的设置在设备类型初始化函数中设置。

对于pc-dimm设备,这个函数就是pc_dimm_class_init中了。

    DeviceClass *dc = DEVICE_CLASS(oc);
    PCDIMMDeviceClass *ddc = PC_DIMM_CLASS(oc);
    MemoryDeviceClass mdc = MEMORY_DEVICE_CLASS(oc);
    mdc->get_addr = pc_dimm_md_get_addr;
    mdc->set_addr = pc_dimm_md_set_addr;

从设备类型到接口类型

在上面这段代码中有一个有意思的地方就是怎么从设备类型PC_DIMM_CLASS转换到接口类型MEMORY_DEVICE_CLASS的

让我们来看一眼:

#define MEMORY_DEVICE_CLASS(klass) \
     OBJECT_CLASS_CHECK(MemoryDeviceClass, (klass), TYPE_MEMORY_DEVICE)

#define OBJECT_CLASS_CHECK(class_type, class, name) \
        ((class_type *)object_class_dynamic_cast_assert(OBJECT_CLASS(class), (name), \
                                          __FILE__, __LINE__, __func__))

经过这两个宏,最后会落到函数object_class_dynamic_cast()。

而这个函数就是沿着klass->interfaces链表查找名字为TYPE_MEMORY_DEVICE的类型。如果找到了唯一的,那就范围它。

怎么样,现在是不是能看清楚这个函数的意义,以及设备类到接口类的转换了?

Last updated