QEMU源码全解析22 —— QOM介绍(11)

接前一篇文章:QEMU源码全解析21 —— QOM介绍(10)

本文内容参考:

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

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

特此致谢!

上回书说到由打device_init_func函数经过以下层层调用,最终来到了object_initialize_with_type函数。

device_init_func -> qdev_device_add -> qdev_device_add_from_qdict -> qdev_new ->

object_new -> object_new_with_type -> object_initialize_with_type -> object_init_with_type

本文对object_initialize_with_type函数进行深入解析。

object_init_with_type函数仍然在qom/object.c中,代码如下:

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);
    }
}

简单来讲,object_new函数通过传进来的typename参数找到对应的TypeImpl,再调用object_new_with_type函数。为了便于理解和加深印象,再次贴出代码:

bject *object_new(const char *typename)
{
    TypeImpl *ti = type_get_by_name(typename);
 
    return object_new_with_type(ti);
}

object_new_with_type函数首先调用type_initialize函数确保类型已经经过初始化,然后分配type->instance_size作为大小分配对象的实际空间,接着调用object_initialize_with_type对对象进行初始化。再次贴出代码如下:

static Object *object_new_with_type(Type type)
{
    Object *obj;
    size_t size, align;
    void (*obj_free)(void *);
 
    g_assert(type != NULL);
    type_initialize(type);
 
    size = type->instance_size;
    align = type->instance_align;
 
    /*
     * Do not use qemu_memalign unless required.  Depending on the
     * implementation, extra alignment implies extra overhead.
     */
    if (likely(align <= __alignof__(qemu_max_align_t))) {
        obj = g_malloc(size);
        obj_free = g_free;
    } else {
        obj = qemu_memalign(align, size);
        obj_free = qemu_vfree;
    }
 
    object_initialize_with_type(obj, size, type);
    obj->free = obj_free;
 
    return obj;
}
​

object_initialize_with_type函数的主要工作是对object_init_with_type和object_post_init_with_type函数进行调用。再次贴出代码如下:

tatic void object_initialize_with_type(Object *obj, size_t size, TypeImpl *type)
{
    type_initialize(type);

    g_assert(type->instance_size >= sizeof(Object));
    g_assert(type->abstract == false);
    g_assert(size >= type->instance_size);

    memset(obj, 0, type->instance_size);
    obj->class = type->class;
    object_ref(obj);
    object_class_property_init_all(obj);
    obj->properties = g_hash_table_new_full(g_str_hash, g_str_equal,
                                            NULL, object_property_free);
    object_init_with_type(obj, type);
    object_post_init_with_type(obj, 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);
    }
}

后者(object_post_init_with_type函数)调用TypeImpl的instance_post_init回调成员完成对象初始化之后的工作。object_post_init_with_type函数同样在qom/object.c中,代码如下:

static void object_post_init_with_type(Object *obj, TypeImpl *ti)
{
    if (ti->instance_post_init) {
        ti->instance_post_init(obj);
    }

    if (type_has_parent(ti)) {
        object_post_init_with_type(obj, type_get_parent(ti));
    }
}

本回就讲到这里,下一回结合一个实例再次对此流程进行解析。

猜你喜欢

转载自blog.csdn.net/phmatthaus/article/details/132031690