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

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

本文内容参考:

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

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

C函数学习(2):GLib HashTable函数_glib 哈希表-CSDN博客

特此致谢!

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

从模板生成类和类的实例化

本回继续解析QEMU类Java反射机制的整个流程。

在QEMU中,每一个Module回模拟某种设备,那么就定义一种类型TypeImpl来表示此种设备。

完整的函数调用链为:

type_init()

---> type_register_static()

---> type_register()

---> type_register_internal()

---> type_new()

---> type_table_add()

上一回解析完了type_register_internal函数中的type_new函数,接下来该调用type_table_add函数了。为了便于理解和回顾,再次贴出type_register_internal函数源码,在qom/object.c中,如下:

static TypeImpl *type_register_internal(const TypeInfo *info)
{
    TypeImpl *ti;
    ti = type_new(info);
 
    type_table_add(ti);
    return ti;
}

前文书已讲过:

type_new函数已经将TypeInfo virtio_blk_info中的信息赋给了函数中新建(调用g_malloc0()动态创建)的TypeImpl对象,并使ti指向了这段内存。接下来就是调用type_table_add函数,将这个对象添加(插入)到全局表type_table中。

type_table_add函数也在qom/object.c中,代码如下:

static void type_table_add(TypeImpl *ti)
{
    assert(!enumerating_types);
    g_hash_table_insert(type_table_get(), (void *)ti->name, ti);
}

type_table_lookup()之前在type_new函数中也遇到过,也在qom/object.c中,代码如下:

static GHashTable *type_table_get(void)
{
    static GHashTable *type_table;

    if (type_table == NULL) {
        type_table = g_hash_table_new(g_str_hash, g_str_equal);
    }

    return type_table;
}

type_table_get函数比较简单易懂,如果type_table为NULL即之前没有创建过,那么就调用g_hash_table_new函数进行创建。之后再调用此函数时,就直接返回创建的type_teble了。

g_hash_table_new函数用于创建一个hash表;g_hash_table_insert函数用于向(创建的)hash表中插入条目,插入的条目必须是一个key-value对。

这里,key对应的是(void *)ti->name,而value对应的是ti本身。

至此,由TypeImpl已经创建了类。但类初始化class_init(本例中是virtio_blk_class_init)函数还没有被调用,这个类还处于纸面的状态(type_init函数用于注册类。每一层都有class_init,用于从TypeImpl生产xxxClass)。到此也就相当于Java反射中的第1步。

流程中的更多步骤,请看下回。