wordpress网站 frp穿透,wordpress邮箱头像,app推广多少钱一个,建设网站的流程图接前一篇文章#xff1a;QEMU源码全解析16 —— QOM介绍#xff08;5#xff09; 本文内容参考#xff1a;
《趣谈Linux操作系统》 —— 刘超#xff0c;极客时间
《QEMU/KVM》源码解析与应用 —— 李强#xff0c;机械工业出版社
特此致谢#xff01; 上一回讲解了Q…接前一篇文章QEMU源码全解析16 —— QOM介绍5 本文内容参考
《趣谈Linux操作系统》 —— 刘超极客时间
《QEMU/KVM》源码解析与应用 —— 李强机械工业出版社
特此致谢 上一回讲解了QOM的第二部分 —— 类型的初始化重点分析了type_initialize函数。类的初始化是通过type_initialize函数完成的。下边以其中一条路径来看type_initialize函数的调用过程。
通过上一回的type_initialize函数代码可以知道其是static的也就是说仅在qom/object.c文件内有效。这就好办多了直接在文件中搜索type_initialize关键字就好了。一共有以下几处调用
1type_initialize() - type_initialize()
这就是上一回讲的递归初始化所有父类型。
2object_initialize_with_type() - type_initialize()
3object_new_with_type() - type_initialize()
4object_class_by_name() - type_initialize()
5object_class_get_parent() - type_initialize()
6object_class_foreach_tramp() - type_initialize()
7type_initialize_interface() - type_initialize()
下边以其中一条路径来看type_initialize的调用过程。
QEMU会在qemu_init函数中调用qemu_create_machine函数。代码如下
qemu_create_machine(machine_opts_dict);
qemu_create_machine函数在同文件softmmu/vl.c中代码如下
static void qemu_create_machine(QDict *qdict)
{MachineClass *machine_class select_machine(qdict, error_fatal);object_set_machine_compat_props(machine_class-compat_props);current_machine MACHINE(object_new_with_class(OBJECT_CLASS(machine_class)));object_property_add_child(object_get_root(), machine,OBJECT(current_machine));object_property_add_child(container_get(OBJECT(current_machine),/unattached),sysbus, OBJECT(sysbus_get_default()));if (machine_class-minimum_page_bits) {if (!set_preferred_target_page_bits(machine_class-minimum_page_bits)) {/* This would be a board error: specifying a minimum smaller than* a targets compile-time fixed setting.*/g_assert_not_reached();}}cpu_exec_init_all();page_size_init();if (machine_class-hw_version) {qemu_set_hw_version(machine_class-hw_version);}/** Get the default machine options from the machine if it is not already* specified either by the configuration file or by the command line.*/if (machine_class-default_machine_opts) {QDict *default_opts keyval_parse(machine_class-default_machine_opts, NULL, NULL,error_abort);qemu_apply_legacy_machine_options(default_opts);object_set_properties_from_keyval(OBJECT(current_machine), default_opts,false, error_abort);qobject_unref(default_opts);}
}函数一开始调用了select_machine函数该函数仍然在同文件中代码如下
static MachineClass *select_machine(QDict *qdict, Error **errp)
{const char *optarg qdict_get_try_str(qdict, type);GSList *machines object_class_get_list(TYPE_MACHINE, false);MachineClass *machine_class;Error *local_err NULL;if (optarg) {machine_class find_machine(optarg, machines);qdict_del(qdict, type);if (!machine_class) {error_setg(local_err, unsupported machine type);}} else {machine_class find_default_machine(machines);if (!machine_class) {error_setg(local_err, No machine specified, and there is no default);}}g_slist_free(machines);if (local_err) {error_append_hint(local_err, Use -machine help to list supported machines\n);error_propagate(errp, local_err);}return machine_class;
}
进而由select_machine函数中的find_default_machine函数来找默认的machine类型。fine_default_machine函数也是在softmmu/vl.c中代码如下
static MachineClass *find_default_machine(GSList *machines)
{GSList *el;MachineClass *default_machineclass NULL;for (el machines; el; el el-next) {MachineClass *mc el-data;if (mc-is_default) {assert(default_machineclass NULL Multiple default machines);default_machineclass mc;}}return default_machineclass;
}
回到上一级select_machine函数中。该函数中有这样一行代码
GSList *machines object_class_get_list(TYPE_MACHINE, false);
select_machine函数调用object_class_get_list函数以得到所有TYPE_MACHINE类型组成的链表。
oject_class_get_list函数在qom/object.c中代码如下
GSList *object_class_get_list(const char *implements_type,bool include_abstract)
{GSList *list NULL;object_class_foreach(object_class_get_list_tramp,implements_type, include_abstract, list);return list;
}
object_class_foreach函数在同文件中代码如下
void object_class_foreach(void (*fn)(ObjectClass *klass, void *opaque),const char *implements_type, bool include_abstract,void *opaque)
{OCFData data { fn, implements_type, include_abstract, opaque };enumerating_types true;g_hash_table_foreach(type_table_get(), object_class_foreach_tramp, data);enumerating_types false;
}
可以看到object_class_foreach函数会对type_table中所有类型调用object_class_foreach_tramp函数即最终会对类型哈希表type_table中的每一个元素调用object_class_foreach_tramp函数。
object_class_foreach_tramp函数仍然在qom/object.c中代码如下
static void object_class_foreach_tramp(gpointer key, gpointer value,gpointer opaque)
{OCFData *data opaque;TypeImpl *type value;ObjectClass *k;type_initialize(type);k type-class;if (!data-include_abstract type-abstract) {return;}if (data-implements_type !object_class_dynamic_cast(k, data-implements_type)) {return;}data-fn(k, data-opaque);
}
object_class_foreach_tramp函数中会调用type_initialize函数。这样在执行select_machine函数的时候就顺带把所有类型都初始化了。
至此QOM的第二部分 —— 类型的初始化就介绍完了。