接前一篇文章:QEMU源码全解析17 —— QOM介绍(6)
本文内容参考:
《趣谈Linux操作系统》 —— 刘超,极客时间
《QEMU/KVM》源码解析与应用 —— 李强,机械工业出版社
特此致谢!
上一回完成了对于QOM的第二部分 —— 类型的初始化的讲解。本回继续往下讲解。
前文说过,QOM整个运作包括3个部分:类型的注册、类型的初始化以及对象的初始化。但是这里需要加一个部分 —— 类型的层次结构(这就有点像桃花三结义,后续四弟——赵云赵子龙)。
从上一回讲的type_initilize函数可以看到,类型初始化时会初始化父类型,因此有必要对于类型的层次结构进行专门的介绍,QOM通过这种层次结构实现了类似C++等面向对象语言中的继承概念。
仍以前文中的edu设备为例。为了便于理解和加深印象,再次贴出edu设备相关代码。在hw/misc/edu.c中:
static void pci_edu_register_types(void)
{static InterfaceInfo interfaces[] = {{ INTERFACE_CONVENTIONAL_PCI_DEVICE },{ },};static const TypeInfo edu_info = {.name = TYPE_PCI_EDU_DEVICE,.parent = TYPE_PCI_DEVICE,.instance_size = sizeof(EduState),.instance_init = edu_instance_init,.class_init = edu_class_init,.interfaces = interfaces,};type_register_static(&edu_info);
}
type_init(pci_edu_register_types)
在edu设备的类型信息edu_info结构中有一个parent成员,这就指定了edu_info的父类型的名称。edu设备的父类型是TYPE_PCI_DEVICE,表明edu设备被设计成一个PCI设备。TYPE_PCI_DEVICE的定义在include/hw/pci/pci.h中,如下所示:
#define TYPE_PCI_DEVICE "pci-device"
TYPE_PCI_DEVICE的类型信息在hw/pci/pci.c中,代码如下:
static const TypeInfo pci_device_type_info = {.name = TYPE_PCI_DEVICE,.parent = TYPE_DEVICE,.instance_size = sizeof(PCIDevice),.abstract = true,.class_size = sizeof(PCIDeviceClass),.class_init = pci_device_class_init,.class_base_init = pci_device_class_base_init,
};
其父类型(对于edu设备类型TYPE_PCI_EDU_DEVICE来说是爷类型)是TYPE_DEVICE,在include/hw/qdev-core.h中定义,如下:
#define TYPE_DEVICE "device"
TYPE_DEVICE的类型信息在hw/core/qdev.c中,代码如下:
static const TypeInfo device_type_info = {.name = TYPE_DEVICE,.parent = TYPE_OBJECT,.instance_size = sizeof(DeviceState),.instance_init = device_initfn,.instance_post_init = device_post_init,.instance_finalize = device_finalize,.class_base_init = device_class_base_init,.class_init = device_class_init,.abstract = true,.class_size = sizeof(DeviceClass),.interfaces = (InterfaceInfo[]) {{ TYPE_VMSTATE_IF },{ TYPE_RESETTABLE_INTERFACE },{ }}
};
再往上追根溯源,TYPE_DEVICE的父类型(对于edu设备类型TYPE_PCI_EDU_DEVICE来说是曾祖类型)是TYPE_OBJECT,在include/qom/object.h中定义,如下:
#define TYPE_OBJECT "object"
TYPE_OBJECT的类型信息在qom/object.c中(转回到object.c这个文件了),代码如下:
static const TypeInfo object_info = {.name = TYPE_OBJECT,.instance_size = sizeof(Object),.class_init = object_class_init,.abstract = true,
};
TYPE_OBJECT没有父类了,也就是说到TYPE_OBJECT这就到头了,它是所有能够初始化实例的最终祖先。
回顾一下,edu类型的层次关系为:
TYPE_PCI_EDU_DEVICE -> TYPE_PCI_DEVICE -> TYPE_DEVICE -> TYPE_OBJECT
这里,我不由得想起了封神榜,二郎神杨戬的师傅是玉鼎真人,玉鼎真人的师傅是元始天尊,元始天尊的师傅是鸿钧祖师。在封神榜里到鸿钧老祖这就到头了,什么截教、阐教、道教,好的坏的都是鸿钧老祖的徒子徒孙(当然,封神榜里还能更进一步,西方教的两个教主就不属于鸿钧祖师这一支,而是混鲲道人这一支,也就是说真正的根是鸿钧和混鲲的师傅创始元灵)。讲虚拟化愣讲出《封神榜》来了,回来吧,回来吧。
类似于device,所有interface的祖先都是TYPE_INTERFACE,在include/qom/object.h中定义,如下:
#define TYPE_INTERFACE "interface"
TYPE_INTERFACE的类型信息也在qom/object.c中(就在TYPE_OBJECT上边),代码如下:
static const TypeInfo interface_info = {.name = TYPE_INTERFACE,.class_size = sizeof(InterfaceClass),.abstract = true,
};
还是得回到《封神榜》,这个TYPE_INTERFACE就相当于西方教那一支。也就是说理论上TYPE_OBJECT和TYPE_INTERFACE还应该有一个共同的父亲,即类、接口的父亲,我看应该是系统。不过QEMU中就没再往上追了。
欲知后事如何,且看下回分解。