qemu的模块笔记

qemu/module.h中的模块类型定义

cpp 复制代码
typedef enum {
    MODULE_INIT_MIGRATION,    // 1. 迁移功能初始化
    MODULE_INIT_BLOCK,        // 2. 块设备层初始化
    MODULE_INIT_OPTS,         // 3. 命令行/配置选项解析初始化
    MODULE_INIT_QOM,          // 4. QEMU 对象模型(核心框架)初始化
    MODULE_INIT_TRACE,        // 5. 跟踪调试系统初始化
    MODULE_INIT_XEN_BACKEND,  // 6. Xen 虚拟化后端初始化
    MODULE_INIT_LIBQOS,       // 7. 服务质量(QoS)控制初始化
    MODULE_INIT_FUZZ_TARGET,  // 8. 模糊测试目标初始化
    MODULE_INIT_MAX           // 枚举边界值(无实际功能)
} module_init_type;

#define block_init(function) module_init(function, MODULE_INIT_BLOCK)
#define opts_init(function) module_init(function, MODULE_INIT_OPTS)
#define type_init(function) module_init(function, MODULE_INIT_QOM)
#define trace_init(function) module_init(function, MODULE_INIT_TRACE)
#define xen_backend_init(function) module_init(function, MODULE_INIT_XEN_BACKEND)
#define libqos_init(function) module_init(function, MODULE_INIT_LIBQOS)
#define fuzz_target_init(function) module_init(function, MODULE_INIT_FUZZ_TARGET)
#define migration_init(function) module_init(function, MODULE_INIT_MIGRATION)

#define module_init(function, type)                                         \
static void __attribute__((constructor)) do_qemu_init_ ## function(void)    \
{                                                                           \
    register_module_init(function, type);                                   \
}

其中,utils/module.c中的register_module_init函数

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

    e = g_malloc0(sizeof(*e));
    e->init = fn;
    e->type = type;
    l = find_type(type);
    QTAILQ_INSERT_TAIL(l, e, node);
}

全局保存的链表数组,根据模块类型可以找到相应的列表,列表再找到类

cpp 复制代码
static ModuleTypeList init_type_list[MODULE_INIT_MAX];
static bool modules_init_done[MODULE_INIT_MAX];

列表的定义

cpp 复制代码
typedef struct ModuleEntry
{
    void (*init)(void);            // type_init注册函数,
    QTAILQ_ENTRY(ModuleEntry) node;
    module_init_type type;
} ModuleEntry;

typedef QTAILQ_HEAD(, ModuleEntry) ModuleTypeList;

比如:object的注册函数type_init(register_types)
module_init(register_types, MODULE_INIT_QOM)
转换成在main函数之前执行的函数

cpp 复制代码
static void __attribute__((constructor)) do_qemu_init_register_types(void)    
{                                                                           
    register_module_init(register_types, MODULE_INIT_QOM);                                   
}

再调用register_module_init函数添加到QOM的列表中

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

    e = g_malloc0(sizeof(*e));
    e->init = fn;
    e->type = type;
    l = find_type(type);
    QTAILQ_INSERT_TAIL(l, e, node);
}

main函数之前只是将函数添加到列表,在main执行到最终会调用

main()
└─ qemu_init() // softmmu/vl.c
└─ qemu_init_subsystems() // softmmu/runstate.c
└─ module_call_init(MODULE_INIT_QOM)
└─ 遍历队列,对每个 e->init() 调用
└─ test_czj_register_types()
└─ type_register_static(&test_czj_info)
qemu_init_subsystems初始化子系统

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

module_call_init的代码实现

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

最终调用注册函数register_types

cpp 复制代码
static void register_types(void)
{
    static const TypeInfo interface_info = {
        .name = TYPE_INTERFACE,
        .class_size = sizeof(InterfaceClass),
        .abstract = true,
    };

    static const TypeInfo object_info = {
        .name = TYPE_OBJECT,
        .instance_size = sizeof(Object),
        .class_init = object_class_init,
        .abstract = true,
    };
    type_interface = type_register_internal(&interface_info);
    type_register_internal(&object_info);
}