Qemu: virtio 对象模型 QOM(进行中)

40 篇文章 9 订阅
8 篇文章 0 订阅

 

3. 类型层次结构

可以通过通过TypeInfo找到类的继承关系

PCI DEVICE 类的父类是DEVICE 

 

DEVICE类的父类是OBJECT

OBJECT 没有父类,是顶层类

所有接口的顶层类是 TYPE_INTERFACE

type_initialize 中分配class类型的结构,等于C++中的一个类,类型信息

PCIDeviceClass 是 PCI Devcie 类

DeviceClass 是设备类的信息

通过device_type_info,将TYPE_DEVICE(类名字)和类DeviceClass(类结构)关联起来

类的内存布局

 

初始化父类的内部域部分

当前类的类型初始化,就是每个类注册的class_init 方法

完成 ObjectClass 到 PCIDeviceClass的转换,就是父类到子类的转换工作

object_class_dynamic_cast 父类到子类的转换工作,type_get_by_name得到目标类型的TypeImpl

type_is_ancestor 判断 target_type 是否是 type的祖先类

4. 对象的构造和初始化

  1. 类型的注册:每个类型指定一个TypeInfo注册到系统,系统运行时把TypeInfo转换为TypeImpl放到Hash表中
  2. 类型的初始化:对Hash表中每个类型进行初始化,设置TypeImpl中的域,并调用class_init,系统总有了所有类型的信息
  3. 对象创建:根据QEMU的命令行参数,创建对应的实例对象,也就是各个类型的object

这里调用的就是注册的 instance_init 函数,对象的大小 instance_size 就是XxxState 大小,每个对象都对应一个XXXState结构体

对象继承关系,对象之间也是父对象和子对象的关系,与类一样

只有在命令行指定了设备或者热插一个设备之后才会有object的创建,类型和对象是通过Object的class域关联在一起的

对象为 VirtIOPCIProxy,class 类型为 VirtioPCIClass,父对象是PCIDevice。

PCIDevice的父对象是DeviceState

DeiveState 的对象是 Object

关联关系见

QOM对象构造三部曲

  1. 类型的构造,通过TypeInfo构造一个TypeImpl的哈希表,main函数之前完成
  2. 类型的初始化,这是在main中进行的
  3. 类对象的构造,只有在命令行指定了对应的设备时候,才会创建对象

qdev_device_add -> object_new -> xxx_instance_init, 只是构造了对象,大小,分配内存等,还没有赋值,赋值在 realize 里面

(gdb) bt
#0  0x00005555558a58be in virtio_net_instance_init (obj=0x5555577a35a0) at /home/liufeng/workspace/src/ovs-dpdk/qemu/hw/net/virtio-net.c:2112
#1  0x0000555555c4dd7f in object_init_with_type (obj=0x5555577a35a0, ti=0x55555656b640) at qom/object.c:353
#2  0x0000555555c4df3d in object_initialize_with_type (data=0x5555577a35a0, size=8856, type=0x55555656b640) at qom/object.c:384
#3  0x0000555555c4df8d in object_initialize (data=0x5555577a35a0, size=8856, typename=0x555555e71609 "virtio-net-device") at qom/object.c:392
#4  0x00005555558d6d43 in virtio_instance_init_common (proxy_obj=0x55555779b430, data=0x5555577a35a0, vdev_size=8856, vdev_name=0x555555e71609 "virtio-net-device") at /home/liufeng/workspace/src/ovs-dpdk/qemu/hw/virtio/virtio.c:2239
#5  0x0000555555bb6436 in virtio_net_pci_instance_init (obj=0x55555779b430) at hw/virtio/virtio-pci.c:2474
#6  0x0000555555c4dd7f in object_init_with_type (obj=0x55555779b430, ti=0x555556597990) at qom/object.c:353
#7  0x0000555555c4df3d in object_initialize_with_type (data=0x55555779b430, size=42000, type=0x555556597990) at qom/object.c:384
#8  0x0000555555c4e580 in object_new_with_type (type=0x555556597990) at qom/object.c:546
#9  0x0000555555c4e5bd in object_new (typename=0x5555565a6a90 "virtio-net-pci") at qom/object.c:556
#10 0x000055555599e169 in qdev_device_add (opts=0x5555565a6a40, errp=0x7fffffffdbc8) at qdev-monitor.c:608
#11 0x00005555559a6a2b in device_init_func (opaque=0x0, opts=0x5555565a6a40, errp=0x0) at vl.c:2281
#12 0x0000555555d9a716 in qemu_opts_foreach (list=0x555556343ca0 <qemu_device_opts>, func=0x5555559a69ed <device_init_func>, opaque=0x0, errp=0x0) at util/qemu-option.c:1106
#13 0x00005555559abf24 in main (argc=29, argv=0x7fffffffdf98, envp=0x7fffffffe088) at vl.c:4576
(gdb) f 10
#10 0x000055555599e169 in qdev_device_add (opts=0x5555565a6a40, errp=0x7fffffffdbc8) at qdev-monitor.c:608
608         dev = DEVICE(object_new(driver));
(gdb) p driver
$1 = 0x5555565a6a90 "virtio-net-pci"

qdev_device_add -> object_property_set_bool-> xxxx_realize

(gdb) bt
#0  0x00005555558a4f9b in virtio_net_device_realize (dev=0x5555577a35a0, errp=0x7fffffffd610) at /home/liufeng/workspace/src/ovs-dpdk/qemu/hw/net/virtio-net.c:1951
#1  0x00005555558d7939 in virtio_device_realize (dev=0x5555577a35a0, errp=0x7fffffffd670) at /home/liufeng/workspace/src/ovs-dpdk/qemu/hw/virtio/virtio.c:2522
#2  0x0000555555a54272 in device_set_realized (obj=0x5555577a35a0, value=true, errp=0x7fffffffd8b8) at hw/core/qdev.c:826
#3  0x0000555555c5196e in property_set_bool (obj=0x5555577a35a0, v=0x5555577b1890, name=0x555555e70f96 "realized", opaque=0x5555577a6d70, errp=0x7fffffffd8b8) at qom/object.c:1984
#4  0x0000555555c4fbd8 in object_property_set (obj=0x5555577a35a0, v=0x5555577b1890, name=0x555555e70f96 "realized", errp=0x7fffffffd8b8) at qom/object.c:1176
#5  0x0000555555c52cdb in object_property_set_qobject (obj=0x5555577a35a0, value=0x5555577b17e0, name=0x555555e70f96 "realized", errp=0x7fffffffd8b8) at qom/qom-qobject.c:27
#6  0x0000555555c4feb6 in object_property_set_bool (obj=0x5555577a35a0, value=true, name=0x555555e70f96 "realized", errp=0x7fffffffd8b8) at qom/object.c:1242
#7  0x0000555555bb62d1 in virtio_net_pci_realize (vpci_dev=0x55555779b430, errp=0x7fffffffd8b8) at hw/virtio/virtio-pci.c:2451
#8  0x0000555555bb47df in virtio_pci_realize (pci_dev=0x55555779b430, errp=0x7fffffffd8b8) at hw/virtio/virtio-pci.c:1856
#9  0x0000555555b13550 in pci_qdev_realize (qdev=0x55555779b430, errp=0x7fffffffd970) at hw/pci/pci.c:2028
#10 0x0000555555bb4b90 in virtio_pci_dc_realize (qdev=0x55555779b430, errp=0x7fffffffd970) at hw/virtio/virtio-pci.c:1930
#11 0x0000555555a54272 in device_set_realized (obj=0x55555779b430, value=true, errp=0x7fffffffdb50) at hw/core/qdev.c:826
#12 0x0000555555c5196e in property_set_bool (obj=0x55555779b430, v=0x5555577ab990, name=0x555555deb95a "realized", opaque=0x55555779ae90, errp=0x7fffffffdb50) at qom/object.c:1984
#13 0x0000555555c4fbd8 in object_property_set (obj=0x55555779b430, v=0x5555577ab990, name=0x555555deb95a "realized", errp=0x7fffffffdb50) at qom/object.c:1176
#14 0x0000555555c52cdb in object_property_set_qobject (obj=0x55555779b430, value=0x5555577ab8e0, name=0x555555deb95a "realized", errp=0x7fffffffdb50) at qom/qom-qobject.c:27
#15 0x0000555555c4feb6 in object_property_set_bool (obj=0x55555779b430, value=true, name=0x555555deb95a "realized", errp=0x7fffffffdb50) at qom/object.c:1242
#16 0x000055555599e26b in qdev_device_add (opts=0x5555565a6a40, errp=0x7fffffffdbc8) at qdev-monitor.c:627
#17 0x00005555559a6a2b in device_init_func (opaque=0x0, opts=0x5555565a6a40, errp=0x0) at vl.c:2281
#18 0x0000555555d9a716 in qemu_opts_foreach (list=0x555556343ca0 <qemu_device_opts>, func=0x5555559a69ed <device_init_func>, opaque=0x0, errp=0x0) at util/qemu-option.c:1106
#19 0x00005555559abf24 in main (argc=29, argv=0x7fffffffdf98, envp=0x7fffffffe088) at vl.c:4576

init 后调用 realize 方法,填充对象各种属性

5. 属性

类属性:ObjectClass 的 properties 域

对象属性:Object 的 properties 域

GHashTable 中存着名字到 ObjectProperty的映射

opaque指向具体的属性

属性的操作接口

对象属性添加 object_property_add

 

对象属性设定 object_property_set

property_set_bool 设定具体的属性

object_property_set_bool

PCI设备的类初始化 pci_device_class_init ,设定了 realize 为 pci_qdev_realize

pci_qdev_realize 会调用 PCIDeviceClass 的 realize,这个会在具体的子类中被赋值 pci_xxx_device_realize

先 class 的 realize ,再试 object的realize

先 virtio_net_pci_realize ,再 device_set_realized -> virtio_device_realize--> virtio_net_device_realize

 

 

bool 属性添加 object_property_add_bool

child 属性添加 object_property_add_child

link 属性添加 object_property_add_link

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

  • 0
    点赞
  • 3
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值