接前一篇文章: QEMU源码全解析39 —— Machine(9)
本文内容参考:
《 QEMU /KVM》源码解析与应用 —— 李强,机械工业出版社
特此致谢!
前边几篇文章围绕MACHINE函数的定义进行了探索,最终得到了MACHINE函数的代码,在include/hw/boards.h中,如下:
- static inline G_GNUC_UNUSED MachineState *MACHINE(const void *obj)
- {
- return OBJECT_CHECK(MachineState, obj, TYPE_MACHINE);
- }
并且得到了OBJECT_CHECK宏展开后的函数代码:
- static inline G_GNUC_UNUSED MachineState *MACHINE(const void *obj)
- {
- return ((MachineState*)object_dynamic_cast_assert(OBJECT(obj), ("machine"), __FILE__, __LINE__, __func__));
- }
现在要回过头来,看看qemu_create_machine函数(softmmu/vl.c中)的实际调用。代码片段如下:
current_machine = MACHINE(object_new_with_class(OBJECT_CLASS(machine_class)));
老版本 QEMU 代码中这一句是这样:
current_machine = MACHINE(object_new(object_class_get_name(OBJECT_CLASS(machine_class))));
之前MACHINE函数是重点,现在其参数object_new_with_class以及object_new函数成为了关注焦点。其均在qom/object.c中,代码如下:
- Object *object_new(const char *typename)
- {
- TypeImpl *ti = type_get_by_name(typename);
-
- return object_new_with_type(ti);
- }
- Object *object_new_with_class(ObjectClass *klass)
- {
- return object_new_with_type(klass->type);
- }
可以看到,甭管是哪一个函数,最终都会调用到object_new_with_type函数。不过这里要先看看新老两个版本的差异细节,也就是怎样“殊途同归”的。
先说新版本。新版本调用的是object_new_with_class(OBJECT_CLASS(machine_class)),这个machine_class是qemu_create_machine函数第一步以下函数得到的:
MachineClass *machine_class = select_machine(qdict, &error_fatal);
这一步的细节可以参看本系列之前文章: QEMU源码全解析34 —— Machine(4)
OBJECT_CLASS是一个宏,在include/qom/object.h中定义,代码如下:
- /**
- * OBJECT_CLASS:
- * @class: A derivative of #ObjectClass.
- *
- * Converts a class to an #ObjectClass. Since all objects are #Objects,
- * this function will always succeed.
- */
- #define OBJECT_CLASS(class) \
- ((ObjectClass *)(class))
而ObjectClass结构的定义在include/qemu/typedefs.h中,如下:
typedef struct ObjectClass ObjectClass;
struct ObjectClass的定义在include/qom/object.h中,代码如下:
- /**
- * struct ObjectClass:
- *
- * The base for all classes. The only thing that #ObjectClass contains is an
- * integer type handle.
- */
- struct ObjectClass
- {
- /* private: */
- Type 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;
- };
最终用到的是ObjectClass中的Type type成员。
再来看老版本。老版本调用的是object_new(object_class_get_name(OBJECT_CLASS(machine_class)))。OBJECT_CLASS宏和machine_class上边都已经说过了,object_class_get_name函数在qom/object.c中,代码如下:
- const char *object_class_get_name(ObjectClass *klass)
- {
- return klass->type->name;
- }
看一下ObjectClass结构中Type类型的定义,在include/qom/object.h中,代码如下:
- struct TypeImpl;
- typedef struct TypeImpl *Type;
从这里就可以看到,实际上Type和TypeImpl是同宗同源的,TypeImpl就是struct TYpeImpl,而Type是struct TypeImpl *。
object_new函数中还调用了type_get_by_name函数,其同样在qom/object.c中,代码如下:
- static TypeImpl *type_get_by_name(const char *name)
- {
- if (name == NULL) {
- return NULL;
- }
-
- return type_table_lookup(name);
- }
type_table_lookup函数在同文件中,代码如下:
- static TypeImpl *type_table_lookup(const char *name)
- {
- return g_hash_table_lookup(type_table_get(), name);
- }
以上过程可能比较容易乱,我们在从头捋一下。
- 新版本
新版本调用的是object_new_with_class(OBJECT_CLASS(machine_class)) 。逐层展开如下:
object_new_with_class(OBJECT_CLASS(machine_class)) --->
object_new_with_class(((ObjectClass *)(machine_class))) --->
object_new_with_type(((ObjectClass *)(machine_class))->type)
- 老版本
老版本调用的是object_new(object_class_get_name(OBJECT_CLASS(machine_class)))。逐层展开如下:
object_new(object_class_get_name(OBJECT_CLASS(machine_class))) --->
object_new(object_class_get_name(((ObjectClass *)(machine_class)))) --->
object_new(((ObjectClass *)(machine_class))->type->name) --->
object_new_with_type(type_get_by_name(((ObjectClass *)(machine_class))->type->name))
从两者最后(一行)代码的对比就能看得出来,新版本比旧版本省了一道事。明明ObjectClass->type可以直接获得,老版本还非得先ObjectClass->type->name再通过type_get_by_name回溯回ObjectClass->type。我看这次更新是很应该的且是要点赞的。
Machine函数最终将新建的MachineState对象返回给了current_machine。
current_machine = MACHINE(object_new_with_class(OBJECT_CLASS(machine_class)));
current_machine是一个MachineState类型的指针,其在hw/core/machine.c中定义,如下:
MachineState *current_machine;
MachineState结构的定义在include/hw/boards.h中,如下:
OBJECT_DECLARE_TYPE(MachineState, MachineClass, MACHINE)
OBJECT_DECLARE_TYPE宏在此不展开了,只需要知道MachineState是从struct MachineState来的:
typedef struct MachineState MachineState;
struct MachineState的定义也在include/hw/boards.h中,如下:
- /**
- * MachineState:
- */
- struct MachineState {
- /*< private >*/
- Object parent_obj;
-
- /*< public >*/
-
- void *fdt;
- char *dtb;
- char *dumpdtb;
- int phandle_start;
- char *dt_compatible;
- bool dump_guest_core;
- bool mem_merge;
- bool usb;
- bool usb_disabled;
- char *firmware;
- bool iommu;
- bool suppress_vmdesc;
- bool enable_graphics;
- ConfidentialGuestSupport *cgs;
- HostMemoryBackend *memdev;
- /*
- * convenience alias to ram_memdev_id backend memory region
- * or to numa container memory region
- */
- MemoryRegion *ram;
- DeviceMemoryState *device_memory;
-
- ram_addr_t ram_size;
- ram_addr_t maxram_size;
- uint64_t ram_slots;
- BootConfiguration boot_config;
- char *kernel_filename;
- char *kernel_cmdline;
- char *initrd_filename;
- const char *cpu_type;
- AccelState *accelerator;
- CPUArchIdList *possible_cpus;
- CpuTopology smp;
- struct NVDIMMState *nvdimms_state;
- struct NumaState *numa_state;
- };
至此,兜兜转转了一大圈,有关主板(Machine)的对象才创建完毕。接下来很多设备(CPU、内存等)的初始化,都是围绕着主板的对象展开的,后面会常常看到current_machine。
欲知后事如何,且看下回分解。