QEMU源码全解析18 —— QOM介绍(7)

88 篇文章 19 订阅
本文深入探讨QEMU中的QOM(Quantum Object Model)的类型层次结构,揭示其如何实现类似面向对象语言中的继承概念。以edu设备为例,解析从TYPE_PCI_EDU_DEVICE到TYPE_OBJECT的类型链,类比于《封神榜》中的师徒关系,阐述了在QEMU中设备类型的层级和继承关系。
摘要由CSDN通过智能技术生成

接前一篇文章: QEMU源码全解析17 —— QOM介绍(6)

本文内容参考:

《趣谈 Linux操作系统 》 —— 刘超, 极客时间

QEMU /KVM》源码解析与应用 —— 李强,机械工业出版社

特此致谢!

上一回完成了对于QOM的第二部分 —— 类型的初始化的讲解。本回继续往下讲解。

前文说过,QOM整个运作包括3个部分:类型的注册、类型的初始化以及对象的初始化。但是这里需要加一个部分 —— 类型的层次结构(这就有点像桃花三结义,后续四弟——赵云赵子龙)。

从上一回讲的type_initilize函数可以看到,类型初始化时会初始化父类型,因此有必要对于类型的层次结构进行专门的介绍,QOM通过这种层次结构实现了类似C++等面向对象语言中的继承概念。

仍以前文中的edu设备为例。为了便于理解和加深印象,再次贴出edu设备相关代码。在hw/misc/edu.c中:

  1. static void pci_edu_register_types(void)
  2. {
  3. static InterfaceInfo interfaces[] = {
  4. { INTERFACE_CONVENTIONAL_PCI_DEVICE },
  5. { },
  6. };
  7. static const TypeInfo edu_info = {
  8. .name = TYPE_PCI_EDU_DEVICE,
  9. .parent = TYPE_PCI_DEVICE,
  10. .instance_size = sizeof(EduState),
  11. .instance_init = edu_instance_init,
  12. .class_init = edu_class_init,
  13. .interfaces = interfaces,
  14. };
  15. type_register_static(&edu_info);
  16. }
  17. 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中,代码如下:

  1. static const TypeInfo pci_device_type_info = {
  2. .name = TYPE_PCI_DEVICE,
  3. .parent = TYPE_DEVICE,
  4. .instance_size = sizeof(PCIDevice),
  5. .abstract = true,
  6. .class_size = sizeof(PCIDeviceClass),
  7. .class_init = pci_device_class_init,
  8. .class_base_init = pci_device_class_base_init,
  9. };

其父类型(对于edu设备类型TYPE_PCI_EDU_DEVICE来说是爷类型)是TYPE_DEVICE,在include/hw/qdev-core.h中定义,如下:

#define TYPE_DEVICE "device"

TYPE_DEVICE的类型信息在hw/core/qdev.c中,代码如下:

  1. static const TypeInfo device_type_info = {
  2. .name = TYPE_DEVICE,
  3. .parent = TYPE_OBJECT,
  4. .instance_size = sizeof(DeviceState),
  5. .instance_init = device_initfn,
  6. .instance_post_init = device_post_init,
  7. .instance_finalize = device_finalize,
  8. .class_base_init = device_class_base_init,
  9. .class_init = device_class_init,
  10. .abstract = true,
  11. .class_size = sizeof(DeviceClass),
  12. .interfaces = (InterfaceInfo[]) {
  13. { TYPE_VMSTATE_IF },
  14. { TYPE_RESETTABLE_INTERFACE },
  15. { }
  16. }
  17. };

再往上追根溯源,TYPE_DEVICE的父类型(对于edu设备类型TYPE_PCI_EDU_DEVICE来说是曾祖类型)是TYPE_OBJECT,在include/qom/object.h中定义,如下:

#define TYPE_OBJECT "object"

TYPE_OBJECT的类型信息在qom/object.c中(转回到object.c这个文件了),代码如下:

  1. static const TypeInfo object_info = {
  2. .name = TYPE_OBJECT,
  3. .instance_size = sizeof(Object),
  4. .class_init = object_class_init,
  5. .abstract = true,
  6. };

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上边),代码如下:

  1. static const TypeInfo interface_info = {
  2. .name = TYPE_INTERFACE,
  3. .class_size = sizeof(InterfaceClass),
  4. .abstract = true,
  5. };

还是得回到《封神榜》,这个TYPE_INTERFACE就相当于西方教那一支。也就是说理论上TYPE_OBJECT和TYPE_INTERFACE还应该有一个共同的父亲,即类、接口的父亲,我看应该是系统。不过 QEMU 中就没再往上追了。

欲知后事如何,且看下回分解。

举报

选择你想要举报的内容(必选)
  • 内容涉黄
  • 政治相关
  • 内容抄袭
  • 涉嫌广告
  • 内容侵权
  • 侮辱谩骂
  • 样式问题
  • 其他