QEMU源码全解析14 —— QOM介绍(3)

接前一篇文章:QEMU源码全解析13 ------ QOM介绍(2)

本文内容参考:

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

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

特此致谢!

上回书讲到了QOM中第一部分------类型的注册,讲了一半,本文接着往下讲。

进入QEMU的main函数不久,就以MODULE_INIT_QOM为参数调用了函数module_call_init(也是上文书讲过的)。那么具体是什么时候调用的module_call_init(MODULE_INIT_QOM)?在QEMU源码qemu-7.1.0(7.1.0版本源码)中搜索此关键字,会有很多地方,那么哪一个才是main函数不久后调用到的?

QEMU源码全解析7 ------ QEMU主函数中我曾经讲过main函数,是在softmmu/main.c中,为了便于理解和加深印象,再次贴出源码:

cpp 复制代码
int qemu_main(int argc, char **argv, char **envp)
{
    int status;

    qemu_init(argc, argv, envp);
    status = qemu_main_loop();
    qemu_cleanup();

    return status;
}

#ifndef CONFIG_COCOA
int main(int argc, char **argv)
{
    return qemu_main(argc, argv, NULL);
}
#endif

主函数所在的位置是在softmmu目录下,那么理论上应该从上述关键字搜索结果中找到同目录下的那个module_call_init(MODULE_INIT_QOM),它最有可能是我们要找的。在softmmu目录下的runstate.c中确实有一处调用,代码如下:

cpp 复制代码
void qemu_init_subsystems(void)
{
    Error *err = NULL;

    os_set_line_buffering();

    module_call_init(MODULE_INIT_TRACE);

    qemu_init_cpu_list();
    qemu_init_cpu_loop();
    qemu_mutex_lock_iothread();

    atexit(qemu_run_exit_notifiers);

    module_call_init(MODULE_INIT_QOM);
    module_call_init(MODULE_INIT_MIGRATION);

    runstate_init();
    precopy_infrastructure_init();
    postcopy_infrastructure_init();
    monitor_init_globals();

    if (qcrypto_init(&err) < 0) {
        error_reportf_err(err, "cannot initialize crypto: ");
        exit(1);
    }

    os_setup_early_signal_handling();

    bdrv_init_with_whitelist();
    socket_init();
}

是在qemu_init_subsystems函数中调用了module_call_init(MODULE_INIT_QOM);。而qemu_init_subsystems函数又是在qemu_init函数中被调用的,代码片段如下(softmmu/vl.c中):

cpp 复制代码
void qemu_init(int argc, char **argv, char **envp)
{
    QemuOpts *opts;
    QemuOpts *icount_opts = NULL, *accel_opts = NULL;
    QemuOptsList *olist;
    int optind;
    const char *optarg;
    MachineClass *machine_class;
    bool userconfig = true;
    FILE *vmstate_dump_file = NULL;

    qemu_add_opts(&qemu_drive_opts);
    qemu_add_drive_opts(&qemu_legacy_drive_opts);
    qemu_add_drive_opts(&qemu_common_drive_opts);
    qemu_add_drive_opts(&qemu_drive_opts);
    qemu_add_drive_opts(&bdrv_runtime_opts);

    ......

    qemu_init_subsystems();

    ......

}

这就很清楚了,函数调用链为:main() -> qemu_main() -> qemu_init() -> qemu_init_subsystems() -> module_call_init(MODULE_INIT_QOM)。

弄清楚这一点之后,回到主题。为便于理解,再贴一下module_call_init函数代码(util/module.c中):

cpp 复制代码
void module_call_init(module_init_type type)
{
    ModuleTypeList *l;
    ModuleEntry *e;

    if (modules_init_done[type]) {
        return;
    }

    l = find_type(type);

    QTAILQ_FOREACH(e, l, node) {
        e->init();
    }

    modules_init_done[type] = true;
}

module_call_int函数执行了init_type_list[MODULE_INIT_QOM]链表上每一个ModuleEntry的init函数。

仍然以edu为例,该类型的init函数是pci_edu_register_types(前文中讲到的hw/misc/edu.c中的一句:type_init(pci_edu_register_types)),该函数在hw/misc/edu.c中,代码如下:

cpp 复制代码
static void pci_edu_register_types(void)
{
    static InterfaceInfo interfaces[] = {
        { INTERFACE_CONVENTIONAL_PCI_DEVICE },
        { },
    };
    static const TypeInfo edu_info = {
        .name          = TYPE_PCI_EDU_DEVICE,
        .parent        = TYPE_PCI_DEVICE,
        .instance_size = sizeof(EduState),
        .instance_init = edu_instance_init,
        .class_init    = edu_class_init,
        .interfaces = interfaces,
    };

    type_register_static(&edu_info);
}
type_init(pci_edu_register_types)

pci_edu_register_types函数唯一的工作是构造了一个TypeInfo类型的edu_info,并将其作为参数调用了type_register_static。

更多细节和分析请看下回。

相关推荐
enjoy嚣士5 天前
Windows10下安装arm64架构的centos
qemu·aarch64 linux·arm64 linux·arm64 centos
x-cmd19 天前
[x-cmd] QEMU 10.2.0 发布:虚拟机实时更新与性能飞跃的技术深度解读
安全·qemu·虚拟机·x-cmd
yao0003719 天前
基于QEMU+OpenSBI+edk2的riscv启动流程解析
qemu·riscv·uefi·bios·固件·opensbi
tianyuanwo20 天前
KVM 虚拟化启动失败深度解析:从硬件到软件的系统性故障排除
kvm·virsh create
三雷科技21 天前
qemu-img 使用手册(含详细案例)
qemu
人间打气筒(Ada)23 天前
GlusterFS实现KVM高可用及热迁移
分布式·虚拟化·kvm·高可用·glusterfs·热迁移
SmartRadio1 个月前
基于ESP32-S3+Barrier实现多电脑KVM共享方案(无缝切换+剪贴板/文件共享)
电脑·esp32·kvm·远程·虚拟键盘·虚拟鼠标
SmartRadio1 个月前
基于RK3568实现多电脑KVM共享方案(HDMI采集+虚拟USB键鼠+无缝切换+剪贴板/文件共享)
运维·服务器·网络·电脑·kvm·rk3568
SmartRadio1 个月前
ESP32-S3实现KVM远控+云玩功能 完整方案
运维·python·计算机外设·esp32·kvm·云玩
河码匠1 个月前
libvirt xml 配置文件说明
qemu·kvm·libvirt