面向对象的设备模型
书接上回,说到device设备在设置了realized属性后会调用DeviceClass的realize函数进行初始化。那这个函数究竟是什么的?
要说清楚这件事,还得找一个具体的设备来说才能够看得清。
qemu中的函数重载
DeviceClass类型中的realize成员在device_class_init()初始化函数中并没有被设置。这个函数的具体对应是在DeviceClass的子类型的类型初始化函数中设置的。
比如PCIDeviceClass就是DeviceClass的一个子类型。在它的类型初始化函数pci_device_class_init中可以看到下面这段代码:
k->realize = pci_qdev_realize;
所以在qemu的设备模型中其实采用了面向对象的编程方法。
面向对象的设备模型
讲了这么多,恐怕大家也听晕了。正所谓耳听为虚,眼见为实。我们来画一个图,看看e1000这个设备面向对象模型的样子。
+--------------------------+ +----------------------+
| | | |
| ObjectClass | <-------------------------| Object |
| class_init | | instance_init |
| | |(object_instance_init)|
+--------------------------+ +----------------------+
| |
| |
| |
v v
+--------------------------+ +----------------------+
| | | |
| DeviceClass | <--------------------- | DeviceState |
| class_init | | instance_init |
| (device_class_init) | | (device_initfn) |
| | | |
| realize | overwrite by child class | |
| unrealize | | |
+--------------------------+ +----------------------+
| |
| |
| |
v v
+--------------------------+ +----------------------+
| | | |
| PCIDeviceClass | <--------------------- | PCIDevice |
| class_init | | instance_init |
| (pci_device_class_init)| | (NULL) |
| realize | | |
| (pci_qdev_realize) | call PCIDevice->realize | |
| unrealize | | |
| (pci_qdev_unrealize) | | |
+--------------------------+ +----------------------+
| |
| |
| |
v v
+--------------------------+ +----------------------+
| | | |
| E1000BaseClass | <-------------------- | E1000State |
| class_init | | instance_init |
| (e1000_class_init) | | (e1000_instance_init)|
| realize | | |
| (pci_e1000_realize) | | |
| unrealize | | |
| | | |
+--------------------------+ +----------------------+
在这张图中体现了这么几点:
某个类型可以是另一个类型的子类型
某个设备实例包含了父类型的实例
实例和类型之间一一对应
类型的成员可以被子类重写
到这里,感觉终于可以说对qemu的设备模型有了那么一点点的了解。
Last updated