DeviceClass实例化细节
上节描述的设备模型抽象了的实例化流程,正是因为是一个抽象的实例化过程,虽然看着很简单,但也失去了很多真实场景下丰富的细节。
那现在我们来看看DeviceClass的实例化。因为很多具体的设备的父类就是这个DeviceClass,所以对这个类型实例化过程的了解对理解Qemu中大部分设备的初始化有很重要的帮助。
+--------------------------+ +----------------------+
| | | |
| 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 | | |
+--------------------------+ +----------------------+这张图显示了DeviceClass相关的父类和对应的对象之间的关系。而我们现在关注的就是它的实例化函数device_initfn。
device_initfn
这个函数并不长,看着也很简单。
就我所知,这个函数主要做了两件事:
给设备设置了三个共有的属性: realized, hotpluggable, hotplugged
根据每个类型定义时的props字段,设置各自的属性
设备属性的设置
先来讲讲这个属性的设置是设置的什么。
当我们运行Qemu的时候,通常会在命令行写上一串参数来表示虚拟机的硬件配置。或者我们通过Qemu monitor添加设备时输入的硬件参数。
比如:
我们就看pc-dimm设备,其中有参数memdev=ram0。
从命令行上,这个参数的作用其实是关联pc-dimm和memory-backend-ram。那在代码中是如何做的呢?
先来看pc-dimm设备的属性props定义:
再回过去看device_initfn中那个对props的循环。在这里就关联了pc-dimm和memory-backend。
realized属性的功效
那接着看看这个属性的被设置时都发生了些什么。
从截取的代码片段中可以看到,当属性被设置时会调用DeviceClass中的realize函数。而这个realized函数就是那个被隐藏了的实例化套路。而很多设备初始化的细节都隐藏在realized函数中。
注:你再往细了看,device_set_realized函数本身也隐藏着很多实现的细节,这里我们就不展开了。
到这里我想大家一定会有两个问题。
这个属性是什么时候设置的
这个realize函数长什么样
那我们兵分两路,先来看看这个属性是什么时候设置的。
谁动了我的realized属性
这个东西还真不好找,而且可能存在多个设置属性的路径,我尝试用下面一个代码片段解释其中一个路径。
这下明确了,当我们生成一个设备对象(object)后,就会调用方法来设置它的realized属性。
也就是我们会人为得去触发这个事件。
一个真实的realize函数
既然刚才讲到了pc-dimm,那我们就来看看pc-dimm的realize。
通常这个函数在class_init中设置,所以我们看到在pc_dimm_class_init中realize被设置成了pc_dimm_realize。
打开这个函数pc_dimm_realize可以看到它会进一步调用子类PCDIMMDeviceClass的realize。
这样就形成了一个类似面向对象的初始化过程。
Last updated
Was this helpful?