六安商业网站建设费用,做网站要考虑的,客户管理系统方案,网站开发怎么去接单接前一篇文章#xff1a; 上一回对于virtio_balloon_pci_realize函数进行了详细解析。最后讲到在virtio_balloon_pci_realize函数的最后一步调用了object_property_set函数#xff0c;从而导致了virtio_device_realize函数的执行。本回就来对于virtio_device_realize函数进行…接前一篇文章 上一回对于virtio_balloon_pci_realize函数进行了详细解析。最后讲到在virtio_balloon_pci_realize函数的最后一步调用了object_property_set函数从而导致了virtio_device_realize函数的执行。本回就来对于virtio_device_realize函数进行解析。
为了便于理解再次贴出virtio_device_realize函数的源码在hw/virtio/virtio.c中如下
static void virtio_device_realize(DeviceState *dev, Error **errp)
{VirtIODevice *vdev VIRTIO_DEVICE(dev);VirtioDeviceClass *vdc VIRTIO_DEVICE_GET_CLASS(dev);Error *err NULL;/* Devices should either use vmsd or the load/save methods */assert(!vdc-vmsd || !vdc-load);if (vdc-realize ! NULL) {vdc-realize(dev, err);if (err ! NULL) {error_propagate(errp, err);return;}}virtio_bus_device_plugged(vdev, err);if (err ! NULL) {error_propagate(errp, err);vdc-unrealize(dev);return;}vdev-listener.commit virtio_memory_listener_commit;vdev-listener.name virtio;memory_listener_register(vdev-listener, vdev-dma_as);QTAILQ_INSERT_TAIL(virtio_list, vdev, next);
}
virtio_device_realize函数其实也是一个通用函数是类型为TYPE_VIRTIO_DEVICE抽象设备的具现化函数。所有的virtio设备在初始化的时候都会调用这个函数。
1virtio_device_realize函数首先得到virtio设备所属的类。代码片段如下 VirtIODevice *vdev VIRTIO_DEVICE(dev);VirtioDeviceClass *vdc VIRTIO_DEVICE_GET_CLASS(dev);
2然后调用具体类的realize函数对于virtio balloon设备来说是virtio_balloon_device_realize函数。代码片段如下 if (vdc-realize ! NULL) {vdc-realize(dev, err);if (err ! NULL) {error_propagate(errp, err);return;}}
3接下来调用virtio_bus_device_plugged函数将virtio设备挂到virtio总线上。代码片段如下 virtio_bus_device_plugged(vdev, err);if (err ! NULL) {error_propagate(errp, err);vdc-unrealize(dev);return;}
4其后调用memory_listener_register函数注册内存监听器。代码片段如下 memory_listener_register(vdev-listener, vdev-dma_as);
memory_listener_register函数在include/exec/memory.h中声明其原型如下
/*** memory_listener_register: register callbacks to be called when memory* sections are mapped or unmapped into an address* space** listener: an object containing the callbacks to be called* filter: if non-%NULL, only regions in this address space will be observed*/
void memory_listener_register(MemoryListener *listener, AddressSpace *filter);
该函数将lister此处是vdev-listener注册到filter地址空间此处是vdev-dma_as中当filter地址空间的拓扑结构发生变化时就会调用其链表上的所有listener调用相关回调函数。
5最后调用QTAILQ_INSERT_TAIL()将vdev插入virtio_list尾部。代码片段如下 QTAILQ_INSERT_TAIL(virtio_list, vdev, next);
QTAILQ_INSERT_TAIL是一个宏用于将元素插入到队列的尾部。QTAIL_INSERT_TAIL定义如下include/qemu/queue.h中
#define QTAILQ_INSERT_TAIL(head, elm, field) do { \(elm)-field.tqe_next NULL; \(elm)-field.tqe_circ.tql_prev (head)-tqh_circ.tql_prev; \(head)-tqh_circ.tql_prev-tql_next (elm); \(head)-tqh_circ.tql_prev (elm)-field.tqe_circ; \
} while (/*CONSTCOND*/0)
因此上述代码最终展开为
do { \(vdev)-next.tqe_next NULL; \(vdev)-next.tqe_circ.tql_prev (virtio_list)-tqh_circ.tql_prev; \(virtio_list)-tqh_circ.tql_prev-tql_next (vdev); \(virtio_list)-tqh_circ.tql_prev (vdev)-next.tqe_circ; \
} while (/*CONSTCOND*/0) 欲知后事如何且看下回分解。