QEMU源码全解析 —— 块设备虚拟化(3)

接前一篇文章: QEMU源码全解析 —— 块设备虚拟化(2)

本文内容参考:

《趣谈 Linux操作系统 》 —— 刘超, 极客时间

QEMU /KVM源码解析与应用》 —— 李强,机械工业出版社

特此致谢!

上一回从宏观上讲解了virtio的基本原理,先大致了解一下就好,后面具体用到的时候再从围观、细微处着手进行详解,到时候宏观与微观相结合,就会完全掌握virtio了。本回回到主线中,开始讲解在QEMU初始化阶段的存储虚拟化即设备虚拟化。

QEMU初始化阶段的块设备虚拟化

如果看过笔者“QEMU源码全解析 —— virtio”系列文章的读者,对于QEMU中的使用C语言实现面向对象思想的机制应该不陌生。那么对于磁盘即块设备来说,机制也是相同的。先来看一下QEMU中virtio block device的相关源码,在hw/block/virtio-blk.c中,如下:

static const TypeInfo virtio_blk_info = {
    .name = TYPE_VIRTIO_BLK,
    .parent = TYPE_VIRTIO_DEVICE,
    .instance_size = sizeof(VirtIOBlock),
    .instance_init = virtio_blk_instance_init,
    .class_init = virtio_blk_class_init,
};

static void virtio_register_types(void)
{
    type_register_static(&virtio_blk_info);
}

type_init(virtio_register_types)

virtio block device这个类的定义是有多层继承关系的。TYPE_VIRTIO_BLK的父类是TYPE_VIRTIO_DEVICE。那么,TYPE_VIRTIO_DEVICE的父类又是谁呢?在hw/virtio/virtio.c中:

static const TypeInfo virtio_device_info = {
    .name = TYPE_VIRTIO_DEVICE,
    .parent = TYPE_DEVICE,
    .instance_size = sizeof(VirtIODevice),
    .class_init = virtio_device_class_init,
    .instance_finalize = virtio_device_instance_finalize,
    .abstract = true,
    .class_size = sizeof(VirtioDeviceClass),
};

static void virtio_register_types(void)
{
    type_register_static(&virtio_device_info);
}

type_init(virtio_register_types)

可见,TYPE_VIRTIO_DEVICE的父类是TYPE_DEVICE。而TYPE_DEVICE的父类是TYPE_OBJECT,参见hw/core/qdev.c中的代码:

static const TypeInfo device_type_info = {
    .name = TYPE_DEVICE,
    .parent = TYPE_OBJECT,
    .instance_size = sizeof(DeviceState),
    .instance_init = device_initfn,
    .instance_post_init = device_post_init,
    .instance_finalize = device_finalize,
    .class_base_init = device_class_base_init,
    .class_init = device_class_init,
    .abstract = true,
    .class_size = sizeof(DeviceClass),
    .interfaces = (InterfaceInfo[]) {
        { TYPE_VMSTATE_IF },
        { TYPE_RESETTABLE_INTERFACE },
        { }
    }
};

static void qdev_register_types(void)
{
    type_register_static(&device_type_info);
}

type_init(qdev_register_types)

到了TYPE_OBJECT就到头了,它是“创始元灵”,没有父类了,所有类都是它的子孙。参见hw/core/object.c中的代码:

static void register_types(void)
{
    static const TypeInfo interface_info = {
        .name = TYPE_INTERFACE,
        .class_size = sizeof(InterfaceClass),
        .abstract = true,
    };

    static const TypeInfo object_info = {
        .name = TYPE_OBJECT,
        .instance_size = sizeof(Object),
        .class_init = object_class_init,
        .abstract = true,
    };

    type_interface = type_register_internal(&interface_info);
    type_register_internal(&object_info);
}

type_init(register_types)

回到virtio block device中来,继承关系总览如下:

TYPE_OBJECT

---> TYPE_DEVICE

---> TYPE_VIRTIO_DEVICE

---> TYPE_VIRTIO_BLK

type_init函数用于注册类。每一层都有class_init,用于从TypeImpl生产xxxClass。TYPE_OBJECT的class_init是object_class_init;TYPE_DEVICE的class_init是device_class_init;TYPE_VIRTIO_DEVICE的class_init是virtio_device_class_init;TYPE_VIRTIO_BLK的class_init是virtio_blk_class_init。

每一层还可能有instance_init(也可能没有),用于将xxxClass初始化为实例。TYPE_DEVICE的instance_init为device_initfn;TYPE_VIRTIO_BLK的instance_init为virtio_blk_instance_init。

更多内容请看下回。