QEMU网络虚拟化(三):面向对象的模型QOM

qemu面向对象的模型:QOM

qemu用结构体实现了一套面向对象的机制,用于实现类和对象的概念,也实现了面向对象的封装、继承、多态。大部分设备模拟代码都会基于这个qom模型。

相关数据结构:

类定义:

struct ObjectClass
{
    /*< private >*/
    Type type;  /* typedef struct TypeImpl *Type  */
    GSList *interfaces;
    const char *object_cast_cache[OBJECT_CLASS_CAST_CACHE];
    const char *class_cast_cache[OBJECT_CLASS_CAST_CACHE];
    ObjectUnparent *unparent;
    GHashTable *properties;
};

对象定义:

struct Object
{
    /*< private >*/
    ObjectClass *class;
    ObjectFree *free; /* 当引用技术为0时,清理垃圾的回调函数 */
    GHashTable *properties; /* 属性的Hash表*/
    uint32_t ref; /* 对象引用计数 */
    Object *parent;
};

属性定义:

typedef struct ObjectProperty
{
    gchar *name;
    gchar *type;
    gchar *description;
    ObjectPropertyAccessor *get; 
    ObjectPropertyAccessor *set;
    ObjectPropertyResolve *resolve;
    ObjectPropertyRelease *release;
    void *opaque;
} ObjectProperty;

每个object对象会有上述对应的属性结构,并用哈希表组织了起来。当需要增加或者删除属性时,可调用object_property_add或object_property_del函数。

定义一个类型:

struct TypeInfo
{   
    const char *name;
    const char *parent;
    
    size_t instance_size; 
    void (*instance_init)(Object *obj); /* 实例初始化 */
    void (*instance_post_init)(Object *obj); 
    void (*instance_finalize)(Object *obj); /* 实例析构 */

    bool abstract;
    size_t class_size;

    void (*class_init)(ObjectClass *klass, void *data); /* 类初始化 */
    void (*class_base_init)(ObjectClass *klass, void *data);
    void (*class_finalize)(ObjectClass *klass, void *data); /* 类析构 */
    void *class_data;               
                                    
    InterfaceInfo *interfaces; 
};
#define type_init(function) module_init(function, MODULE_INIT_QOM) 

type_register函数会根据TypeInfo结构体生成TypeImpl结构体,并将name作为key,创建全局hash表:

struct TypeImpl
{
    const char *name; 
    size_t class_size;
    size_t instance_size;
    void (*class_init)(ObjectClass *klass, void *data); /* 类初始化 */
    void (*class_base_init)(ObjectClass *klass, void *data);
    void *class_data;
    void (*instance_init)(Object *obj); /* 实例初始化 */
    void (*instance_post_init)(Object *obj);
    void (*instance_finalize)(Object *obj);
    bool abstract;
    const char *parent;
    TypeImpl *parent_type; /* 指向父类型 */
    ObjectClass *class;
    int num_interfaces;
    InterfaceImpl interfaces[MAX_INTERFACES];
};

类的基本信息是通过这个TypeImpl体现的

类的数据结构一般包含大量的函数指针,用于对对象进行操作。class对应的init函数可以将这些函数指针初始化。然后所有含有这个类数据结构指针的对象,都可以调用这些函数。 — 共性东西拿出来搞成Class,泛化

对象的数据结构一般包含了大量变量,是对象的一些属性,很明显这些是每个实例特有的,各自不尽相同。instance对应的init函数可以把这些属性初始化,相当于C++中的构造函数。 — 特化的东西构成实例

初始化相关:

已virtio-net-pci为例:

  1. type_init(virtio_net_pci_register) -> register_module_init : 会将virtio_net_pci_register放到全局二维数组中init_type_list,数组成员为ModuleEntry类型,内部有init函数指针,virtio_net_pci_register会赋值给init

  2. main() -> module_call_init(MODULE_INIT_QOM) : 会遍历init_type_list[MODULE_INIT_QOM]中的所有元素,并调用init]
    -> virtio_net_pci_register -> type_register -> type_register_internal -> type_table_add [通过该调用链,对应TypeImpl结构被加入到全局hash表中

  3. main -> select_machine -> object_class_get_list -> object_class_foreach ->object_class_get_list_tramp -> type_initialize

    static void type_initialize(TypeImpl *ti)
    {
    	....
        if (ti->class) { /* 非空,已经初始化过,直接退出 */
            return;
        }
        ...
         if (parent) {
            type_initialize(parent); /* 递归调用,回溯到根节点 */
            ...
            memcpy(ti->class,parent->class,parent->class_size);/* 复制父节点的class结构体,继承的实现本质 */
            ... 
         }
        ...
        if (ti->class_init) {
            ti->class_init(ti->class, ti->class_data); /* 类初始化函数 */
        }
    }
    

    【TypeImpl是一种辅助数据结构,类的创建以及初始化会基于该结构体】

  4. main -> qemu_opts_foreach -> device_init_func -> device_init_func -> qdev_device_add -> object_new : 该调用链会遍历全局保存的QemuOptsList数组(vm_config_groups),找到类型为device的单元,例如对应下面的命令行选项:

    -netdev tap,id=hostnet0,ifname=vnet2,downscript=no
    -device virtio-net-pci,netdev=hostnet0,id=net0,mac=52:54:00:6b:0d:a1,bus=pci.0,addr=0x3
    
    DeviceState *qdev_device_add(QemuOpts *opts, Error **errp)
    {	
    	DeviceClass *dc;
        const char *driver, *path;
        DeviceState *dev;
        BusState *bus = NULL;
        ...
     	driver = qemu_opt_get(opts, "driver"); /* 此处对应virtio-net-pci */
        ...
        dc = qdev_get_device_class(&driver, errp);
        ...
        path = qemu_opt_get(opts, "bus"); /* 寻找对应总线路径,此处对应pci.0 */
        if (path != NULL) {
            bus = qbus_find(path, errp); /* 根据path寻找对应的bus实例 */
            if (!bus) {
                return NULL;
            }
            if (!object_dynamic_cast(OBJECT(bus), dc->bus_type)) {
                error_setg(errp, "Device '%s' can't go on %s bus",
                           driver, object_get_typename(OBJECT(bus)));
                return NULL;
            } /* 总线不匹配 */
        }
        ...
        dev = DEVICE(object_new(driver));  /* 创建设备实例 */
        if (bus) {
            qdev_set_parent_bus(dev, bus); /* 设备与总线关联 */
        }
        ...
        if (qemu_opt_foreach(opts, set_property, dev, &err)) {
            goto err_del_dev;
        } /* 根据opts设置属性,上例会设置的属性有:netdev、mac、addr */
         /* 对于netdev属性,后面会调用set_netdev函数,使得device和netdev发生关联,前面已经具体介绍过 */
    	dev->opts = opts;
        object_property_set_bool(OBJECT(dev), true, "realized", &err); /* 触发realize回调 */
    }
    

    object_new -> object_new_with_type -> object_initialize_with_type -> object_initialize_with_type -> object_init_with_type

    static void object_init_with_type(Object *obj, TypeImpl *ti)
    {
        if (type_has_parent(ti)) {
            object_init_with_type(obj, type_get_parent(ti));/* 回溯到根节点,递归调用 */
        }
        if (ti->instance_init) {
            ti->instance_init(obj); /* 实例初始化函数 */
        }
    }
    
  5. 另外关注一下DeviceClass这个结构体,其中有个realize回调,设备的许多初始化操作是在这个函数中进行的。

    typedef struct DeviceClass {
        /*< private >*/
        ObjectClass parent_class;
        /*< public >*/
        DECLARE_BITMAP(categories, DEVICE_CATEGORY_MAX);
        const char *fw_name;
        const char *desc;
        Property *props;
        bool user_creatable;
        bool hotpluggable;
        /* callbacks */
        DeviceReset reset;
        DeviceRealize realize; /* 更具体的初始化操作 */
        DeviceUnrealize unrealize;
        /* device state */
        const struct VMStateDescription *vmsd;
        /* Private to qdev / bus.  */
        const char *bus_type;
    };
    

    以virtio_net_device_realize为例:

    main -> qemu_opts_foreach -> device_init_func -> qdev_device_add -> object_property_set_bool -> property_set_bool -> device_set_realized -> pci_qdev_realize -> virtio_pci_realize -> object_property_set_qobject -> property_set_bool -> device_set_realized -> virtio_net_device_realize

​ realize这个属性是在object_init_with_type回溯到DeciceClass节点调用对应的instance_init实现的,对应的函数为:

static void device_initfn(Object *obj)
{
 	....
	object_property_add_bool(obj, "realized",
                         device_get_realized, device_set_realized, NULL);
	....
}
  • 1
    点赞
  • 1
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值