接前一篇文章: QEMU源码全解析 —— 块设备虚拟化(7)
本文内容参考:
《趣谈 Linux操作系统 》 —— 刘超,极客时间
《 QEMU /KVM源码解析与应用》 —— 李强,机械工业出版社
特此致谢!
QEMU初始化阶段的块设备虚拟化
从模板生成类和类的实例化
上一回在讲解Java反射机制流程的时候,讲到了第2步,再来回顾一下:
上一回讲解virtio_blk_info中的class_init指向的函数virtio_blk_class_init,解析了DeviceClass和DEVICE_CLASS宏。
static void virtio_blk_class_init(ObjectClass *klass, void *data)
{
DeviceClass *dc = DEVICE_CLASS(klass);
VirtioDeviceClass *vdc = VIRTIO_DEVICE_CLASS(klass);
device_class_set_props(dc, virtio_blk_properties);
dc->vmsd = &vmstate_virtio_blk;
set_bit(DEVICE_CATEGORY_STORAGE, dc->categories);
vdc->realize = virtio_blk_device_realize;
vdc->unrealize = virtio_blk_device_unrealize;
vdc->get_config = virtio_blk_update_config;
vdc->set_config = virtio_blk_set_config;
vdc->get_features = virtio_blk_get_features;
vdc->set_status = virtio_blk_set_status;
vdc->reset = virtio_blk_reset;
vdc->save = virtio_blk_save_device;
vdc->load = virtio_blk_load_device;
vdc->start_ioeventfd = virtio_blk_data_plane_start;
vdc->stop_ioeventfd = virtio_blk_data_plane_stop;
}
本回解析第2行:
VirtioDeviceClass *vdc = VIRTIO_DEVICE_CLASS(klass);
依样画葫芦。
VIRTIO_DEVICE_CLASS是一个宏定义,同样在QEMU源码中不能直接搜索到。要弄清楚VIRTUAL_DEVICE_CLASS,得先从include/hw/virtio/virtio.h中的OBJECT_DECLARE_TYPE讲起。
#define TYPE_VIRTIO_DEVICE "virtio-device"
OBJECT_DECLARE_TYPE(VirtIODevice, VirtioDeviceClass, VIRTIO_DEVICE)
OBJECT_DECLARE_TYPE的相关代码在include/qom/object.h中,代码如下:
/**
* OBJECT_DECLARE_TYPE:
* @InstanceType: instance struct name
* @ClassType: class struct name
* @MODULE_OBJ_NAME: the object name in uppercase with underscore separators
*
* This macro is typically used in a header file, and will:
*
* - create the typedefs for the object and class structs
* - register the type for use with g_autoptr
* - provide three standard type cast functions
*
* The object struct and class struct need to be declared manually.
*/
#define OBJECT_DECLARE_TYPE(InstanceType, ClassType, MODULE_OBJ_NAME) \
typedef struct InstanceType InstanceType; \
typedef struct ClassType ClassType; \
\
G_DEFINE_AUTOPTR_CLEANUP_FUNC(InstanceType, object_unref) \
\
DECLARE_OBJ_CHECKERS(InstanceType, ClassType, \
MODULE_OBJ_NAME, TYPE_##MODULE_OBJ_NAME)
那么带入实际值:
OBJECT_DECLARE_TYPE(VirtIODevice, VirtioDeviceClass, VIRTIO_DEVICE)
得到:
typedef struct VirtIODevice VirtIODevice;
typedef struct VirtioDeviceClass VirtioDeviceClass;
G_DEFINE_AUTOPTR_CLEANUP_FUNC(VirtIODevice, object_unref)
DECLARE_OBJ_CHECKERS(VirtIODevice, VirtioDeviceClass, VIRTIO_DEVICE, TYPE_VIRTIO_DEVICE)
先给出完全展开后的实际值:
DECLARE_OBJ_CHECKERS宏的定义在include/qom/object.h中,如下:
/**
* DECLARE_OBJ_CHECKERS:
* @InstanceType: instance struct name
* @ClassType: class struct name
* @OBJ_NAME: the object name in uppercase with underscore separators
* @TYPENAME: type name
*
* Direct usage of this macro should be avoided, and the complete
* OBJECT_DECLARE_TYPE macro is recommended instead.
*
* This macro will provide the three standard type cast functions for a
* QOM type.
*/
#define DECLARE_OBJ_CHECKERS(InstanceType, ClassType, OBJ_NAME, TYPENAME) \
DECLARE_INSTANCE_CHECKER(InstanceType, OBJ_NAME, TYPENAME) \
\
DECLARE_CLASS_CHECKERS(ClassType, OBJ_NAME, TYPENAME)
DECLARE_INSTANCE_CHECKER宏的定义也在同文件(include/qom/object.h)中,如下:
/**
* DECLARE_INSTANCE_CHECKER:
* @InstanceType: instance struct name
* @OBJ_NAME: the object name in uppercase with underscore separators
* @TYPENAME: type name
*
* Direct usage of this macro should be avoided, and the complete
* OBJECT_DECLARE_TYPE macro is recommended instead.
*
* This macro will provide the instance type cast functions for a
* QOM type.
*/
#define DECLARE_INSTANCE_CHECKER(InstanceType, OBJ_NAME, TYPENAME) \
static inline G_GNUC_UNUSED InstanceType * \
OBJ_NAME(const void *obj) \
{ return OBJECT_CHECK(InstanceType, obj, TYPENAME); }
DECLARE_CLASS_CHECKERS宏的定义当然也在include/qom/object.h中,如下:
/**
* DECLARE_CLASS_CHECKERS:
* @ClassType: class struct name
* @OBJ_NAME: the object name in uppercase with underscore separators
* @TYPENAME: type name
*
* Direct usage of this macro should be avoided, and the complete
* OBJECT_DECLARE_TYPE macro is recommended instead.
*
* This macro will provide the class type cast functions for a
* QOM type.
*/
#define DECLARE_CLASS_CHECKERS(ClassType, OBJ_NAME, TYPENAME) \
static inline G_GNUC_UNUSED ClassType * \
OBJ_NAME##_GET_CLASS(const void *obj) \
{ return OBJECT_GET_CLASS(ClassType, obj, TYPENAME); } \
\
static inline G_GNUC_UNUSED ClassType * \
OBJ_NAME##_CLASS(const void *klass) \
{ return OBJECT_CLASS_CHECK(ClassType, klass, TYPENAME); }
这样,
#define DECLARE_OBJ_CHECKERS(InstanceType, ClassType, OBJ_NAME, TYPENAME) \
DECLARE_INSTANCE_CHECKER(InstanceType, OBJ_NAME, TYPENAME) \
\
DECLARE_CLASS_CHECKERS(ClassType, OBJ_NAME, TYPENAME)
实际上就相当于:
static inline G_GNUC_UNUSED InstanceType *OBJ_NAME(const void *obj)
{
return OBJECT_CHECK(InstanceType, obj, TYPENAME);
}
static inline G_GNUC_UNUSED ClassType *OBJ_NAME##_GET_CLASS(const void *obj)
{
return OBJECT_GET_CLASS(ClassType, obj, TYPENAME);
}
static inline G_GNUC_UNUSED ClassType *OBJ_NAME##_CLASS(const void *klass)
{
return OBJECT_CLASS_CHECK(ClassType, klass, TYPENAME);
}
进一步地,代入调用DECLARE_OBJ_CHECKERS()时传入的实际值:
DECLARE_OBJ_CHECKERS(VirtIODevice, VirtioDeviceClass, VIRTIO_DEVICE, TYPE_VIRTIO_DEVICE)
#define DECLARE_OBJ_CHECKERS(InstanceType, ClassType, OBJ_NAME, TYPENAME) \
DECLARE_INSTANCE_CHECKER(InstanceType, OBJ_NAME, TYPENAME) \
\
DECLARE_CLASS_CHECKERS(ClassType, OBJ_NAME, TYPENAME)
就得到:
DECLARE_INSTANCE_CHECKER(VirtIODevice, VIRTIO_DEVICE, TYPE_VIRTIO_DEVICE)
DECLARE_CLASS_CHECKERS(VirtioDeviceClass, VIRTIO_DEVICE, TYPE_VIRTIO_DEVICE)
进一步得到:
static inline G_GNUC_UNUSED VirtIODevice *VIRTIO_DEVICE(const void *obj)
{
return OBJECT_CHECK(VirtIODevice, obj, TYPE_DEVICE);
}
static inline G_GNUC_UNUSED VirtioDeviceClass *VIRTIO_DEVICE_GET_CLASS(const void *obj)
{
return OBJECT_GET_CLASS(VirtioDeviceClass, obj, TYPE_DEVICE);
}
static inline G_GNUC_UNUSED VirtioDeviceClass *VIRTIO_DEVICE_CLASS(const void *klass)
{
return OBJECT_CLASS_CHECK(VirtioDeviceClass, klass, TYPE_DEVICE);
}
最终得到:
static inline G_GNUC_UNUSED VirtIODevice *VIRTIO_DEVICE(const void *obj)
{
return OBJECT_CHECK(VirtIODevice, obj, "virtio-device");
}
static inline G_GNUC_UNUSED VirtioDeviceClass *VIRTIO_DEVICE_GET_CLASS(const void *obj)
{
return OBJECT_GET_CLASS(VirtioDeviceClass, obj, "virtio-device");
}
static inline G_GNUC_UNUSED VirtioDeviceClass *VIRTIO_DEVICE_CLASS(const void *klass)
{
return OBJECT_CLASS_CHECK(VirtioDeviceClass, klass, "virtio-device");
}
综合所有的内容,
typedef struct VirtIODevice VirtIODevice;
typedef struct VirtioDeviceClass VirtioDeviceClass;
G_DEFINE_AUTOPTR_CLEANUP_FUNC(VirtIODevice, object_unref)
DECLARE_OBJ_CHECKERS(VirtIODevice, VirtioDeviceClass, VIRTIO_DEVICE, TYPE_VIRTIO_DEVICE)
完整内容是:
typedef struct VirtIODevice VirtIODevice;
typedef struct VirtioDeviceClass VirtioDeviceClass;
G_DEFINE_AUTOPTR_CLEANUP_FUNC(VirtIODevice, object_unref)
static inline G_GNUC_UNUSED VirtIODevice *VIRTIO_DEVICE(const void *obj)
{
return OBJECT_CHECK(VirtIODevice, obj, "virtio-device");
}
static inline G_GNUC_UNUSED VirtioDeviceClass *VIRTIO_DEVICE_GET_CLASS(const void *obj)
{
return OBJECT_GET_CLASS(VirtioDeviceClass, obj, "virtio-device");
}
static inline G_GNUC_UNUSED VirtioDeviceClass *VIRTIO_DEVICE_CLASS(const void *klass)
{
return OBJECT_CLASS_CHECK(VirtioDeviceClass, klass, "virtio-device");
}
再次与系统展开内容进行对比:
弄清楚了DEVICE_CLASS的定义,回到主线代码中。
static void virtio_blk_class_init(ObjectClass *klass, void *data)
{
DeviceClass *dc = DEVICE_CLASS(klass);
VirtioDeviceClass *vdc = VIRTIO_DEVICE_CLASS(klass);
……
}
中的
VirtioDeviceClass *vdc = VIRTIO_DEVICE_CLASS(klass);
就是:
static inline G_GNUC_UNUSED VirtioDeviceClass *VIRTIO_DEVICE_CLASS(const void *klass)
{
return OBJECT_CLASS_CHECK(VirtioDeviceClass, klass, "virtio-device");
}
VirtioDeviceClass *vdc = OBJECT_CLASS_CHECK(VirtioDeviceClass, klass, "virtio-device");
这样,反映射调用流程的第2步就解析完了,DeviceClass和VirtioDeviceClass已经生成了。
欲知后事如何,且看下回分解。