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. 对象的构造和初始化
- 类型的注册:每个类型指定一个TypeInfo注册到系统,系统运行时把TypeInfo转换为TypeImpl放到Hash表中
- 类型的初始化:对Hash表中每个类型进行初始化,设置TypeImpl中的域,并调用class_init,系统总有了所有类型的信息
- 对象创建:根据QEMU的命令行参数,创建对应的实例对象,也就是各个类型的object
这里调用的就是注册的 instance_init 函数,对象的大小 instance_size 就是XxxState 大小,每个对象都对应一个XXXState结构体
对象继承关系,对象之间也是父对象和子对象的关系,与类一样
只有在命令行指定了设备或者热插一个设备之后才会有object的创建,类型和对象是通过Object的class域关联在一起的
对象为 VirtIOPCIProxy,class 类型为 VirtioPCIClass,父对象是PCIDevice。
PCIDevice的父对象是DeviceState
DeiveState 的对象是 Object
关联关系见
QOM对象构造三部曲
- 类型的构造,通过TypeInfo构造一个TypeImpl的哈希表,main函数之前完成
- 类型的初始化,这是在main中进行的
- 类对象的构造,只有在命令行指定了对应的设备时候,才会创建对象
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